MPEG4Writer.cpp revision ee4e1b1a63758941460ae79a064249d3a5189443
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_Model[]      = "com.android.model";
677c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[]    = "com.android.version";
687c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[]      = "com.android.build";
697c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
707c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang/* uncomment to include model and build in meta */
727c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1
737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
76bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
8137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
8237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
8325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
8420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
853b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
86d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
87b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
92c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
9370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
94dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
97000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
98000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
998c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
100000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
101000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
102c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
103c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    template<class TYPE>
104c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity)
106c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
107c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mEntryCapacity(entryCapacity),
108c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
109c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
110c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
111c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mElementCapacity, 0);
112c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mEntryCapacity, 0);
113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
114c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
115c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
116c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
117c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
12925f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity);
130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value;
141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
14825f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            if (pos >= mTotalNumTableEntries * mEntryCapacity) {
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            value = (*it)[(pos % (mElementCapacity * mEntryCapacity))];
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nValues  = mNumValuesInCurrEntry % mEntryCapacity;
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity];
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t pos = nEntries * mEntryCapacity + nValues;
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) {
182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0);
193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK_GT(nEntries, 0);
198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity);
200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries);
203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mEntryCapacity;    // # of values in each entry
214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mNumValuesInCurrEntry;  // up to mEntryCapacity
216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
226693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<MediaSource> mSource;
22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
228a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
229a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
230eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
2331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
234bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
235c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
23643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
237e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
238d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
244be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
24513aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStszTableEntries;
249be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStcoTableEntries;
251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<off64_t> *mCo64TableEntries;
252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStscTableEntries;
253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStssTableEntries;
254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mSttsTableEntries;
255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mCttsTableEntries;
256965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
257000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
258000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
259965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
2613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
2623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
2633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
2643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
2653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
2663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
2673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
2683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
2693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
2703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
2713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
2723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
2733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
276548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
27793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
2803c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
28170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
28270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
28393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
28493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
28525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
286872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
287872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
288872a481558350634a3fd5cb67939de288af00ecbJames Dong
289000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
290000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
29237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
2953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
2963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
297b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
298b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
299b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
300215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
301215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
302faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
30393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
30403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
30519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
30619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
307c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
308c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
309c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
310c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
311c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
312c059860c73678a202bfa33062723e8f82fb779d9James Dong
313690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
314690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
31513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
316690f546b0ee548dbfe997df36418e5302ec2d786James Dong
3171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
3181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
3191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
32079761ab096f57c3027fad9556c2bc436672d614eJames Dong
32179761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
32279761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
323965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
32445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
32545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
32643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
3271f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
334965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
342efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
346efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35730ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
358674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
359674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
360de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui      mIsRealTimeRecording(true),
361b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
3621acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
363a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
364a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
365a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
366411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
36730ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
36813aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
3697837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
3707c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang      mMoovExtraSize(0),
37107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
37207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
37307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
37486b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
375ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mStartTimeOffsetMs(-1),
376ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mMetaKeys(new AMessage()) {
3777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    addDeviceMeta();
37830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
37930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
3818bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
3841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
3861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
3871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
392dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
393dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
394dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
395dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
396dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
397dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
398dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
399dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
400dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
401dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
402dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
403dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
404dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
405dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
406dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
407dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
408dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
409dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
41084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
411dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
412dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
413dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
414dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
415dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
416dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
417dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
418dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
419c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
42013210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
421377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
42213210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
423dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
424dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
425dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
426dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
4272dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
428bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
429bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
43029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
431bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
432bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
433acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
434acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At most 2 tracks can be supported.
435acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.size() >= 2) {
436a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("Too many tracks (%zu) to add", mTracks.size());
437acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
438acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
439acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
440acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
441acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
442acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // A track of type other than video or audio is not supported.
443acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
444acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
445acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    bool isAudio = !strncasecmp(mime, "audio/", 6);
446acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    bool isVideo = !strncasecmp(mime, "video/", 6);
447acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (!isAudio && !isVideo) {
448acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("Track (%s) other than video or audio is not supported",
449acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            mime);
450acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
451acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
452acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
453acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At this point, we know the track to be added is either
454acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // video or audio. Thus, we only need to check whether it
455acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // is an audio track or not (if it is not, then it must be
456acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // a video track).
457acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
458acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // No more than one video or one audio track is supported.
459acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    for (List<Track*>::iterator it = mTracks.begin();
460acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong         it != mTracks.end(); ++it) {
461acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        if ((*it)->isAudio() == isAudio) {
462acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            ALOGE("%s track already exists", isAudio? "Audio": "Video");
463acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            return ERROR_UNSUPPORTED;
464acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        }
465acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
466acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
467acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // This is the first track of either audio or video.
468acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
469219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
4712dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
4722dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
476acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
477acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
478acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
479acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
480acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
481a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
482a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
48393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
484a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
485a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
486a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
487a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
488a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
489a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
490a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
491a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
492a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
493a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
494a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
495a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
496a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
4977c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
4987c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
4997c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
5007c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
5017c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
5027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
5037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
5047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
5057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
5067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
5077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
5097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
5107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD
5127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.product.model", val, NULL)
5137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Model, val, n + 1);
5157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
5167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
5187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
5207c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
5217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5227c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
5237c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
5247c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
5252dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
5262dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
5272dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
5282dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
5292dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
5302dec2b5be2056c6d9428897dc672185872d30d17James Dong
53178a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
5322dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
53378a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
5342dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
5352dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
5362dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
5372dec2b5be2056c6d9428897dc672185872d30d17James Dong
5382dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
5392dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
5402dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
54178a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
5422dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
5432dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
5442dec2b5be2056c6d9428897dc672185872d30d17James Dong
54578a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
546a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
54778a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
54878a1a286f736888ae7af8860b2c424af0d978848James Dong    }
54978a1a286f736888ae7af8860b2c424af0d978848James Dong
55078a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
55178a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
55278a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
55378a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
55478a1a286f736888ae7af8860b2c424af0d978848James Dong                ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
55578a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
55678a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
55778a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
55878a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
55978a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
56078a1a286f736888ae7af8860b2c424af0d978848James Dong                }
56178a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
56278a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
56378a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
56478a1a286f736888ae7af8860b2c424af0d978848James Dong            }
5652dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
5662dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
56778a1a286f736888ae7af8860b2c424af0d978848James Dong
5682dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
5692dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
5702dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
5712dec2b5be2056c6d9428897dc672185872d30d17James Dong
5722dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
5732dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
5742dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
5752dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
5762dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
5772dec2b5be2056c6d9428897dc672185872d30d17James Dong
5787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
5797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
5807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
581a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
582a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
5832dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
5842dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
5852dec2b5be2056c6d9428897dc672185872d30d17James Dong}
5862dec2b5be2056c6d9428897dc672185872d30d17James Dong
5872dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
588674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
58925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
592a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
593a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
594a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
595a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
596a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
597a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
598a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
599a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
600a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
601a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
6022dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
6032dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
6042dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
6052dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
6062dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
6072dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6082dec2b5be2056c6d9428897dc672185872d30d17James Dong
6091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
6101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
6111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
6121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
6131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
6141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
6151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
6161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
6171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
618a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
619a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
620d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
621d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
6221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
6231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
6241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
625b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
626b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
627b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
628b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
629b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
6302dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6312dec2b5be2056c6d9428897dc672185872d30d17James Dong
632de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
633de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
634de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
635de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
636de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
637065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
63893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
639a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
640a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
641a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
64293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
643a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
644a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
645a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
646a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
6478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
6488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
6498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
6508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
65143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
6523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
6538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
65477e8ae9967a078770416619e99ddb5b010def312James Dong    /*
65577e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
65677e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
6577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
6587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
65977e8ae9967a078770416619e99ddb5b010def312James Dong     */
66077e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
66177e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
66277e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
66377e8ae9967a078770416619e99ddb5b010def312James Dong
6647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
6657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
6667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * smaller than the reserved free space at the beginning of a file, AND
6677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * when the content of moov box is constructed. Note that video/audio
6687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * frame data is always written to the file but not in the memory.
6697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
6707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
6717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
6727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Moov box needs to be constructed.
6737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
6747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
6757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to set to mStreamableFile so that if
6767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the file is intended to be streamable, it is set to true;
6777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * otherwise, it is set to false. When the value is set to false,
6787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * all the content of the moov box is written immediately to
6797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
6807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * content of the moov box is written to an in-memory cache,
6817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mMoovBoxBuffer, util the following condition happens. Note
6827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
6837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
6847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
6857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 2) While the data of the moov box is written to an in-memory
6867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
6877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * If the data size surpasses the reserved space, subsequent moov
6887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * data could no longer be hold in the in-memory cache. This also
6897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
6907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * _all_ moov data must be written to the end of the file.
6917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory must be set to false to direct the write
6927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
6937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
6947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 3) If the data size in moov box is smaller than the reserved
6957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space after moov box is completely constructed, the in-memory
6967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache copy of the moov box is written to the reserved free
6977b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space. Thus, immediately after the moov is completedly
6987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * constructed, mWriteMoovBoxToMemory is always set to false.
6997b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
7007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = false;
7017837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
7027837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
7037837c17063a4c50bc856ba59418516fdab731de7James Dong
704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7067837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7087837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
7092dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
7102dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
7112dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
7122dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
7132dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
7147837c17063a4c50bc856ba59418516fdab731de7James Dong    }
71543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
71677e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
71777e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
71877e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
71977e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
72077e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
72177e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
72277e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
72377e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
72477e8ae9967a078770416619e99ddb5b010def312James Dong    }
7257837c17063a4c50bc856ba59418516fdab731de7James Dong
7267837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
727c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
7281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
7291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
7301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
7311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
7321acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
7331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
7351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
7361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
7371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
7381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
740a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
741a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
7431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
744a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
74525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
7491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
7501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
7511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
75237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
753674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
75437187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
755a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
756a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
75737187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
758a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
759a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
76037187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
76137187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
76237187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
76337187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
764a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
76537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
766a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
767a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
7681c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
769b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
770411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
771411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
772411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
7731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
7751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
7761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
7781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
7791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
7801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
7811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
7821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
783411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
784b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
7851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
7861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
78713f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
78813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
78913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
79013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
79113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
79213f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
79313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
79413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
79513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
79613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
79713f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
79813f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
7993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
80013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
80113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
80213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
80313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
80413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
80513f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
80613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
80713f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
80813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
80913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
81013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
81113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
81213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
81313f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
81413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
81513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
81613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
81713f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
81813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
81913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
82013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
82113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
82213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
82313f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
82413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
82513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
82613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
82713f6284305e4b27395a23db7882d670bdb1bcae1James Dong
82813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
82913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
83013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
83113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
83213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
83313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
83413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
83513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
83613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
83713f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
83813f6284305e4b27395a23db7882d670bdb1bcae1James Dong
839411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
840411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
841411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
842411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
843411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
8444c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    free(mMoovBoxBuffer);
8454c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    mMoovBoxBuffer = NULL;
846411ba422e3635d534928ffd81abf54f4f291c739James Dong}
84713f6284305e4b27395a23db7882d670bdb1bcae1James Dong
8488bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() {
849674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
85037187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
851411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
852411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
853411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
854411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
855411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
856411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
857411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
858411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
859411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
86237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
8638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
86465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
86520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
86737187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
86837187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
86937187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
87037187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
87120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
8738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
8748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
87520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
87665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
87765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
87865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
87965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
88065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
88165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
882a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
88365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
88420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
88520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
8877837c17063a4c50bc856ba59418516fdab731de7James Dong
88837187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
88937187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
890411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
89137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
89237187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
89337187916a486504acaf83bea30147eb5fbf46ae5James Dong
89420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
8951acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
896c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
8971f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
898c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
8991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
900c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
9011f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
9021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
903c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
9041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
905c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Construct moov box now
9087837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
9097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = mStreamableFile;
9107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
9117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
9127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // for moov box if the file is not streamable.
9137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
9147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
9157b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        CHECK(mMoovBoxBuffer != NULL);
9167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // mWriteMoovBoxToMemory could be set to false in
9207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // MPEG4Writer::write() method
9217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
9227b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mWriteMoovBoxToMemory = false;
9237b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // Content of the moov box is saved in the cache, and the in-memory
9247b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // moov box needs to be written to the file in a single shot.
9257b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
92643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
9277837c17063a4c50bc856ba59418516fdab731de7James Dong
9287837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
929c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
9307837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
931674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
9327837c17063a4c50bc856ba59418516fdab731de7James Dong
9337837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
934c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
9357837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
9367837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
9377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    } else {
9387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        ALOGI("The mp4 file will not be streamable.");
9397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
9407837c17063a4c50bc856ba59418516fdab731de7James Dong
9417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Free in-memory cache for moov box
9427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mMoovBoxBuffer != NULL) {
9437837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
9447837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
9457837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
9467837c17063a4c50bc856ba59418516fdab731de7James Dong    }
9477837c17063a4c50bc856ba59418516fdab731de7James Dong
9480c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
950411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
95137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
954efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
956efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
957efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
958efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
959efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60);
960efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
961efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
962efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
963efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
964efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
99107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
99207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
99307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
994e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeMetaBox();
995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
10032cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
1008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
1009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
10108284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
10118284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
10128284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
10148284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
10158284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
10178284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
1018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
102307ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
102407ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
102507ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
102607ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
102707ec01904613a0bac32caaa8444b4690998faed7James Dong
102807ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
102907ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
103007ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
103107ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
103207ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
103307ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
103407ec01904613a0bac32caaa8444b4690998faed7James Dong    }
103507ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
103607ec01904613a0bac32caaa8444b4690998faed7James Dong}
103707ec01904613a0bac32caaa8444b4690998faed7James Dong
103870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
103907ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
104007ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
104107ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
104207ec01904613a0bac32caaa8444b4690998faed7James Dong    }
104307ec01904613a0bac32caaa8444b4690998faed7James Dong
104470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
104570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
104670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
104770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
104870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
104970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
105070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
105170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
105270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
105313aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
105413aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
105513aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
105613aec890216948b0c364f8f92792129d0335f506James Dong}
105713aec890216948b0c364f8f92792129d0335f506James Dong
105813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
105913aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
106013aec890216948b0c364f8f92792129d0335f506James Dong}
106113aec890216948b0c364f8f92792129d0335f506James Dong
106213aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
106313aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
106413aec890216948b0c364f8f92792129d0335f506James Dong}
106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1066c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1067c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
106820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1069c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
1070c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
1071c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
107220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
107420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
107620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
107720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
107903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
108003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
108103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
108203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
108303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
108403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
108503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
108603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
108703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
108803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
108903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
109003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
109103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1092c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1093c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
109430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
109530ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
109603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1097b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1098b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1099c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1100b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1101c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1102b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1103c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1104b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1105c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1106c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1107c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1108c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1109c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1110b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1111b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1112b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
111343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
111430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1115b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1116c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1117b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1118c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1119c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1120b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1121b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
112230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
112330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
112430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
112530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
11267837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1127674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
11287837c17063a4c50bc856ba59418516fdab731de7James Dong
11297837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
11307837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
11317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1132c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
11331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
11347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // The reserved moov box at the beginning of the file
11357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // is not big enough. Moov box should be written to
11367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the end of the file from now on, but not to the
11377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // in-memory cache.
11387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
11397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // We write partial moov box that is in the memory to
11407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the file first.
1141c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
11427837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
11437837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
11447837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1145674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1146674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
11477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
11487837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
11497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
11507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // All subsequent moov box content will be written
11517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // to the end of the file.
11527837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
11537837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
11547837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
11557837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
11567837c17063a4c50bc856ba59418516fdab731de7James Dong        }
11577837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1158674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
11597837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
11607837c17063a4c50bc856ba59418516fdab731de7James Dong    }
11617837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
11627837c17063a4c50bc856ba59418516fdab731de7James Dong}
11637837c17063a4c50bc856ba59418516fdab731de7James Dong
1164e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1165e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mBoxes.push_back(mWriteMoovBoxToMemory?
1166e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mMoovBoxBufferOffset: mOffset);
1167e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1168e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1169e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1170e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1171e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
11730c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11757837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
11767837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
11830c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1185c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11887837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
11897837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
11907837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
11917837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1192c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
11937837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
11947837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1195c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
11967837c17063a4c50bc856ba59418516fdab731de7James Dong    }
119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1200674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1205674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1210674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1215674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1220674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
122320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
12240c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
1225674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
122807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
122907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
123007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
123107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
123207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
123307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
123407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
123507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
123607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
123707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
123807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
123907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
124007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
124107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
124207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
124307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
124407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
124507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
124607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
124707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
124807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
124907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
125007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
125107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
125207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
125307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
125407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
125507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
125607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
125707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
125807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
125907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
126007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
126107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
126207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
126307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
126407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
126507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
126607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
126707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
126807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
126907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
127007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
127107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
127207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
127307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
127407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
127507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
127607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
127707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
127807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
127907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
128007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
128107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
128207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
128307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
128407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
128507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
128607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
128707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
128807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
128907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
129007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
129107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
129207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
129307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
129407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
129507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
12967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
129707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
129807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
129907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1300e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1301e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1302e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1303e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1304e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
13057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
13067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
13077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1308e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1309e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1310e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1312674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131578a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
131678a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
131778a1a286f736888ae7af8860b2c424af0d978848James Dong}
131878a1a286f736888ae7af8860b2c424af0d978848James Dong
1319d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1320d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1321d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1322d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1323d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1324d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1325956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1326d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1327d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1328d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1329d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
13301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
133177e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
133277e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
133377e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
133477e8ae9967a078770416619e99ddb5b010def312James Dong    }
1335acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1336acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1337acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1338acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1339d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1340d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1341d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1342d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1343d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1344d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1345d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1346d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1347d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1348d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1349d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1350d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1351d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1352d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1353d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1354d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1355d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
135625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
135725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
135825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
135925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
136025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
136125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
136225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
136325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
136425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
136525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
136625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
136725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
136825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1369f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1370a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
137143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
13723c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1373065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1374f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1375a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
13763c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
13773c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
13783c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1379f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
13803c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
13813c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
13823c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
13833c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
138458ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
138558ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
138658ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
138758ae9c530247668f8af36e30d228c716c226b3d4James Dong}
138858ae9c530247668f8af36e30d228c716c226b3d4James Dong
138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
139020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1392bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
139425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1397a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1398a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1399eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1400bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1401c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1402956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1403be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1404c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1405c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1406c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)),
1407c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)),
1408c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1409c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
1410c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
141225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1413548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
141413f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
141513f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
141619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
14178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
14181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
14191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
14201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
14211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
14221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
14231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
14241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1425c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1426c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1427c059860c73678a202bfa33062723e8f82fb779d9James Dong
14281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
14291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1430c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1431c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1432c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1433c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1434c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
14351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
143678a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
143778a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
143878a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
143978a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1440c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1441c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1442c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1443c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
144478a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
144578a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
144678a1a286f736888ae7af8860b2c424af0d978848James Dong    }
14471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
14501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
14511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1452c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1453c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1454c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
14551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1458c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
14591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
146279761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
14631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
14645a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1465377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
14665a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1467c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1468c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
14691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1471965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1472965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1473965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1474965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1475965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1476965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1477c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1478c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1479965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1480965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1481c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1482c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1483c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1484c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1485c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1486c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1487c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
14881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
14891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1490c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
14913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1492c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1493c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1494c059860c73678a202bfa33062723e8f82fb779d9James Dong
1495c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1496c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1497c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1498c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1499c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1500c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1501c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1502c059860c73678a202bfa33062723e8f82fb779d9James Dong
1503c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1504c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1505c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1506c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1507c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1508c059860c73678a202bfa33062723e8f82fb779d9James Dong
150943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
151019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
151119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
151219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
151319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
151419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
151519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
151619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
151719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
151819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
151919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
152019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
152119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificData = malloc(size);
152219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mCodecSpecificDataSize = size;
152319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            memcpy(mCodecSpecificData, data, size);
152419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            mGotAllCodecSpecificData = true;
152519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
152619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
152719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
152819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        uint32_t type;
152919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        const void *data;
153019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        size_t size;
153119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
153219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
153319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
153419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificData = malloc(size);
153519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mCodecSpecificDataSize = size;
153619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                memcpy(mCodecSpecificData, data, size);
153719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber                mGotAllCodecSpecificData = true;
153819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
153919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
154019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
154120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
154220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
154320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
154420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
154520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1546c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1547c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1548c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1549c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1550c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1551c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1552c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1553c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1554c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1555c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1556c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1557c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1558c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1559c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1560c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1561c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
156220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
156320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
156420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
156520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
156620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
156720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
15693856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
157093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
157193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
157293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
157393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
157493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
157593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1576a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
157793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
157893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
157993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
158093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
158193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
158293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
15831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
15841c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
15853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
15861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
15871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
15881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
15891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
15901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15911c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
15923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
15931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
15941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
15951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
15971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
15981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
15991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
16001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
16011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
16021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
16031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
16051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
160643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
16071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1609fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1610a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
16115410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1612fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1613fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1614fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1615fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1616fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1617fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        off64_t offset = chunk->mTrack->isAvc()
1618fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                ? addLengthPrefixedSample_l(*it)
1619fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1620fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1621fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1622fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1623fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
16241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
16271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1628fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
16291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1630fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
16311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1633fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
16343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
16351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
163670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
163770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1638e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
163970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
16401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
164170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
164270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
164370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
16441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1645377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
16461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1648fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
16493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
16501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
16521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
16531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
16541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
16551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
16561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
16571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
16581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
16591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
16601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
16611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
16631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
16653856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1666fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
16671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
16681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
16701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
16711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1672fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
16731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
16741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
16751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1676fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1677fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1678fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
167970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
168070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
168170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
168270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
168370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
168470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
168570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1686fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
16871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1689fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1690fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
16911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16931c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
16943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
16951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1696a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1697fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1698fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
16991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1700fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1701fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1702fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1703fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
17041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
17051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1707de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
1708de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
1709de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
1710de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
1711fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1712de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1713de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
1714de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1715fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1716de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1717de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
1718de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1719fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
17201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1721fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1722fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
17231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17251c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
17263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
17271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
17291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1730e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
17311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
17321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
17331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
17341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
173570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
173670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
17371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
17381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
17411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
17421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
17431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
17441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1745411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
17461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
17471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
175093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1751a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1752a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1753a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1754a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1755a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
175625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
175793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
175819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
175919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
176019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
176170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
176219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
176313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
176413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
176513f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
176613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
176713f6284305e4b27395a23db7882d670bdb1bcae1James Dong
176893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
176993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1770f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1771de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
1772a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1773a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1774a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1775a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1776a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1777a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
177886b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
177986b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1780a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
178186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
178286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
178386b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
178486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
178586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1786a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
1787a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1788a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1789f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1790a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1791f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
179225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
179325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
179425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
179525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
179620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
179720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
179820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
179920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
180020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
180120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1802eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1803c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
180425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1805956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
18061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
180743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
180820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
180925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
181020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
181125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
181225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
181320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
181420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
181537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1816a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
181737187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1818a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1819a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
182037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
182172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track stopping", mIsAudio? "Audio": "Video");
1822eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
182329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1824eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1825eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1826eaae38445a340c4857c1c5569475879a728e63b7James Dong
182720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
182837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
182920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
183020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
183120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
183272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopping", mIsAudio? "Audio": "Video");
183372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSource->stop();
183472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopped", mIsAudio? "Audio": "Video");
183572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
183620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
183720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
1838377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
183937187916a486504acaf83bea30147eb5fbf46ae5James Dong
1840b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
184137187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
184220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
184320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
184425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
184525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
184625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
184725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
184920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
185120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
185237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
1853377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
185420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
185520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
18573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
18583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
18603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
18613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
18623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode(
18643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length) {
18653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
1866a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("findNextStartCode: %p %zu", data, length);
18673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = length;
18693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4  &&
18703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
18713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        --bytesLeft;
18723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (bytesLeft <= 4) {
18743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft = 0; // Last parameter set
18753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return &data[length - bytesLeft];
18773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
18783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
18803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
18813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
18833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
18843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
18853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = findNextStartCode(data, length);
18873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
18883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
188929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
18903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
18913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
18923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
18933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
18943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
18953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
189629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
18973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
18983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
18993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
19003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
19013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
19023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
19033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
19043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
19063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
190729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
19083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
19093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
19123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
19133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
19163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
19203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
19233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4 + 7) {
1925377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = size;
19303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
19363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
19373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
19393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
19403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
19413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
19423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
19433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
19453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
19463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
19473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
19483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
19493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
19503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
19513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
19523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
19533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
195429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
19553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
19563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
19583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
19593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
19613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
19623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
196329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
19643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
19653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
19673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
19683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
19703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
197129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
19723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
19733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
19763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
19773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
19803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
19813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
19823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
19833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
19863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
19873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
19883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
198929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
19903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
19913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
1994377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
19953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
19963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
20003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
20013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
200329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2007377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20111374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
20121374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
20131374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
20141374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
20163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
20193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
202029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20241374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2027548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
202803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
202903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2030548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
203103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
203229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
203303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
203403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
203503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2037377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
203803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
203903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
204003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
20423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
204403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
204503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
204703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
204803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
204903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
20513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
205203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
205303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
20543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
20553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
20563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
20573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
205803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2060b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2061b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2062b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2063b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2064b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
206503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
20663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
20673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
20683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
20693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
20703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
20713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
20723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
20733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
20743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
20753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
20763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
20783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
20793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
20803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
20833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
20843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
20853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
20863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
20873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
20883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
20903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
20913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
20923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
20943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
20953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
20963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
209703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
209803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
209903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
210003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
2101872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2102872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2103872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2104872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2105872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2106872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2107872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2108872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2109872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2110872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2111872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2112872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2113872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2114872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2115872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2116872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2117872a481558350634a3fd5cb67939de288af00ecbJames Dong
211837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
211930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
212013aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
212143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
212213aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
212313aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
212413aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2125965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2126965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2127965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2128965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2129965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2130000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2131a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2132965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2133000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2134000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2135000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
213643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2138e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2139a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2140a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
2141a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
2142a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
2143a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2144de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2145de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2146de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2147de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2148985f838934510983d8a887461e98dca60a6e858fJames Dong
2149d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
215020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
215193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
215220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
215311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    const char *trackName = mIsAudio ? "Audio" : "Video";
215493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
215520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
215620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
215720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
215813aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
215920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
216020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
216120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2162a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2163a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2164a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2165a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2166a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2167a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2168a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2169a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2170a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
217130ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
217230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
217303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
217403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
217503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
2176548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            CHECK(!mGotAllCodecSpecificData);
2177548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
21781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (mIsAvc) {
217903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                status_t err = makeAVCCodecSpecificData(
218003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
218103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
218203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        buffer->range_length());
218343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                CHECK_EQ((status_t)OK, err);
21841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            } else if (mIsMPEG4) {
218503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificDataSize = buffer->range_length();
218603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                mCodecSpecificData = malloc(mCodecSpecificDataSize);
218703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                memcpy(mCodecSpecificData,
218803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                        (const uint8_t *)buffer->data()
218903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                            + buffer->range_offset(),
219003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                       buffer->range_length());
219130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
219230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
219330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
219430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
219530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2196548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
219730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2198a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2199a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2200d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2201d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2202d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2203d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2204d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2205d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2206d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2207d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2208d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2209d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
22101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (mIsAvc) StripStartcode(copy);
2211e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2212b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
2213b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        if (mIsAvc) {
2214b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2215b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2216b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2217b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2218b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2219b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2220050b28a593350047845a45a14cc5026221ac1620James Dong
2221d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
22221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
22231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
22241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2225d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2226d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2227d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2228d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2229d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2230d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2231d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2232d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2233d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2234050b28a593350047845a45a14cc5026221ac1620James Dong
2235d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2236d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2237d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2238d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2239d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
224170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2242f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2243f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
22448428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
22453c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
224648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2247a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
22488428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
224911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
225011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
225111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
225211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
225311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
22548428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
225511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
225611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
225711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
225811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
225911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
22608428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2261a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2262a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2263a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2264a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
226511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
226611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
226711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
226811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
226911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2270000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        if (!mIsAudio) {
2271965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2272965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2273965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2274000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2275965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2276965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2277965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2278965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2279000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2280000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
228111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
228211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
228311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
228411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
228511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2286965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2287a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2288000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2289000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2290000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2291000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2292000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
229311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
229411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
229511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
229611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
229711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2298c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
229943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
230043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
230143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
230243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
230343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
230443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
230543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
230643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
230743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
230843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
230943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
231043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
231143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
231243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
231343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2314000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2315000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2316c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2317000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2318000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2319000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2320000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2321000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2322000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2323000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2324000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2325000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2326000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2327965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2328872a481558350634a3fd5cb67939de288af00ecbJames Dong
2329de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        if (mOwner->isRealTimeRecording()) {
2330872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2331872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2332e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2333e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2334872a481558350634a3fd5cb67939de288af00ecbJames Dong
233511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
233611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
233711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
233811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
233911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2340a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
234111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, previousPausedDurationUs);
2342c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2343c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
23443b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
23453b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
23465a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
23475a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
23485a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
23495a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
23505a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
23515a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
23525a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
23535a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2354c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2355a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGE("timestampUs %" PRId64 " < lastTimestampUs %" PRId64 " for %s track",
235611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                timestampUs, lastTimestampUs, trackName);
235711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
2358c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return UNKNOWN_ERROR;
23598c460498c028888c533ab442be12b6d4b669b965James Dong        }
23608c460498c028888c533ab442be12b6d4b669b965James Dong
236185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // if the duration is different for this sample, see if it is close enough to the previous
236285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // duration that we can fudge it and use the same value, to avoid filling the stts table
236385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // with lots of near-identical entries.
236485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // "close enough" here means that the current duration needs to be adjusted by less
236585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // than 0.1 milliseconds
236685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
236785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
236885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                    + (mTimeScale / 2)) / mTimeScale;
236985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            if (deltaUs > -100 && deltaUs < 100) {
237085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // use previous ticks, and adjust timestamp as if it was actually that number
237185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // of ticks
237285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                currDurationTicks = lastDurationTicks;
237385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                timestampUs += deltaUs;
237485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
237585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        }
237685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen
2377c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2378c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2379c059860c73678a202bfa33062723e8f82fb779d9James Dong
2380a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2381a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2382c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
238379761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2384be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2385be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2386be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2387be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2388965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2389be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2390be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2391c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2392be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2393be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
23948644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2395be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2396a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
239711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, lastTimestampUs);
23988644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2399c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
24008644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
240120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2402d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2403c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2404d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2405d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
240693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
240793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
240893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
240993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2410faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
241193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
241243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
2413c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
241458ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2415c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2416c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2417c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2418c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2419c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2420c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
24211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
242258ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
242358ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
242458ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
242558ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
242658ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
242713aec890216948b0c364f8f92792129d0335f506James Dong
242813aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
242913aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
24301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
24311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
243213aec890216948b0c364f8f92792129d0335f506James Dong        } else {
243313aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
243413aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
243513aec890216948b0c364f8f92792129d0335f506James Dong            } else {
243643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
243743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
243843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
243943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
244043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
244113aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
244213aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2443c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2444c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2445c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
244613aec890216948b0c364f8f92792129d0335f506James Dong                    }
24471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
244813aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
244913aec890216948b0c364f8f92792129d0335f506James Dong                }
245013aec890216948b0c364f8f92792129d0335f506James Dong            }
245113aec890216948b0c364f8f92792129d0335f506James Dong        }
245213aec890216948b0c364f8f92792129d0335f506James Dong
245320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
245425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
245545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2456690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2457f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
245845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2459bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2460be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
246113aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
246243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2463c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
246458ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
24651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
24661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
246713aec890216948b0c364f8f92792129d0335f506James Dong    }
246813aec890216948b0c364f8f92792129d0335f506James Dong
2469be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2470be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2471be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2472c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
24738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
247479761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2475be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2476be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2477be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2478a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2479c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
248079761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2481a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
248279761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2483a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2484a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
248579761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2486a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2487a472613aec322e25891abf5c77bf3f7e3c244920James Dong
248843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
248943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
249043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
249143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
249243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
249343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
249443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
249543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2496c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
249725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
249843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
249943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
250043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2501df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
250211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
2503872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2504a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
2505872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2506365a963142093a1cd8efdcea76b5f65096a5b115James Dong
250737187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
250837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
250937187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
251037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2511365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2512365a963142093a1cd8efdcea76b5f65096a5b115James Dong
251345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
2514c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
251529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
251645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
251745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
251845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2519c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (!mIsAudio && mStssTableEntries->count() == 0) {  // no sync frames for video
252029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
252145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
252245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
252345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
252445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
252545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
252645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
252745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
252845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
252945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
253045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
253143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
253207ec01904613a0bac32caaa8444b4690998faed7James Dong
253307ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
253407ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
253507ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
253607ec01904613a0bac32caaa8444b4690998faed7James Dong    }
253707ec01904613a0bac32caaa8444b4690998faed7James Dong
253843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
253943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
254043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
254143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
254243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
254343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
254443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
254543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
254643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
254743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
254843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
254943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2550c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
255143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
255286b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
255386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
255486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
255586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
255686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
255786b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
255886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
255986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
256086b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
256186b7f47aa7482424cf8fd248f1315311919be3b0James Dong
256286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
256370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
256470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
256586b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
256670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
256707ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
256807ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
256907ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
257007ec01904613a0bac32caaa8444b4690998faed7James Dong
257143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
257243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
257343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
257443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
257570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
257670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
257770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
257870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
257970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
258070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
258170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
258270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
258343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
258443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
258543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2586faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
2587a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
2588c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2589215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2590215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
2591a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
2592bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
259393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
259493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
259593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
259693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2597faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2598bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2599faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2600bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2601faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2602faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2603faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2604faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2605bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2606bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2607faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2608faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2609faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2610faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2611faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2612faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2613bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2614bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2615faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2616faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2617faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2618bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2619bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2620faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2621faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2622faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2623faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2624d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
2625a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
2626e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2627d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2628e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2629e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2630e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
2631a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
2632e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2633e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2634e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2635e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2636de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
2637de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
2638de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
2639de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2640b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2641b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2642b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2643b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
26441c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
26453856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
26461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
26471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
26481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
264913aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
265020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
265120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26523b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2653c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
265420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
265520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2656d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2657d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2658d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2659d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2660690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2661690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2662690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2663690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2664690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
2665690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2666690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2667690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
266829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2669690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2670690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2671690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2672690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2673690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
267429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2675690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2676690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2677690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2678690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2679690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2680690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
268220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
26841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
26858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
2686efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2698b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
2707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
2709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
2714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
2716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
2717965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
2718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
2720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mp4v");
2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("s263");
2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("avc1");
2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
273829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
2762c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
2763c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
276743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(23 + mCodecSpecificDataSize, 128);
2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *fourcc = NULL;
2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "samr";
2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "sawb";
2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fourcc = "mp4a";
2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
279329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
2812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
2817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
282643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
282943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);   // buffer size 24-bit
2844ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier    int32_t bitRate;
2845ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier    bool success = mMeta->findInt32(kKeyBitRate, &bitRate);
2846ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier    mOwner->writeInt32(success ? bitRate : 96000); // max bit rate
2847ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier    mOwner->writeInt32(success ? bitRate : 96000); // avg bit rate
2848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
2850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2853b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2863b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
2864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
286543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
2866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
2869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
2871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
2872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
2873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
2874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
2876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
2877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
2878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
2879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
2881b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01, 0x77, 0x00,
2882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00,
2883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x00, 0x03, 0xe8, 0x00
2884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
2886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
2888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
2895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2902efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
2903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
2904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
2907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2909219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
2910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
29118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
2912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
2914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
2915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
2916b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
292420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
2928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
2930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
2931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
2932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
2933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
2935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
2936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
2938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
2942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
2943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
2947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2948b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
2960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
2962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
2963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
2966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
2967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
2968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2971efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
2972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
2973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
2976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
2977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
2978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
2979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
2980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
2982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
2983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
2984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
2985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // language code
2986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
2987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
2991b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
2992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
2993b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
3010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
3011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
3013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
3014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
3015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
3018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
3019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
3020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
3021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
3024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
302543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
3026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
3028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
3029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3030b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
3037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
3038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
3039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
3040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
3041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
3042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
3043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
3046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
3047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3053000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3054a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
305743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3060000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
3061000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3062000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3063000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3064000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3065000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3066c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3067c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
3068c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
3069c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3070c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
3071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
307320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3074965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
3075965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
3076965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3077965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3078965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3079000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
3080000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3081000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
3082000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
3083000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3084965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
3085c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
3086965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3087965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3088965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3089a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3090c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3091965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3092965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
3093000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3094c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3095c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mCttsTableEntries->get(duration, 1));
3096c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back host byte order
3097c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1);
3098c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
3099965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
3100965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
3101965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
3103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
3104b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
3106b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
3107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
310825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
3109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
3110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
3111b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3112c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
3113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
3114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
3115b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
311620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3117b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
3118b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
3119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
3121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
3122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
312320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3124b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3125b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
3126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
3128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
3129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
3130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
3131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3132b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
313320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
313420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
313507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
313607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
313707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
313807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
313907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
314007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
3141e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() {
3142e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
3143e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
3144e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
3145e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeFourcc("mdta");
3146e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
3147e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
3148e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
3149e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
3150e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3151e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3152e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3153e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
3154e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3155e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3156e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
3157e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
3158e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
3159e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3160e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3161e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3162e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
3163e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
3164e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
3165e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
3166e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3167e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3168e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3169e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3170e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
3171e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3172e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3173e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
3174e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3175e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
3176e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
3177e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3178e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3179e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
31807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
31817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
31827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
31837c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
31847c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
31857c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
31867c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
31877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
31887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
31897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
3190e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
3191e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3192e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
3193e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
31947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
31957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3196e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
3197e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3198e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3199e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3200e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
3201e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3202e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
3203e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
32047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
32057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3206e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
3207e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3208e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3209e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3210e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
3211e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3212e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
32137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
32147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3215e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
3216e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3217e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3218e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
3219e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
3220e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
3221e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3222e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
3223e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3224e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3225e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() {
3226e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3227e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
3228e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
3229e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3230e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3231e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
3232e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeHdlr();
3233e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
3234e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
3235e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3236e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3237e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
323807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
323907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
324007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
324107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
324207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
324307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
324407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
324507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
324607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
3247432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
3248432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
324907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
325007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
325107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
325207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
325307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
325407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
325507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
325607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
325720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3258