MPEG4Writer.cpp revision 10cc12c4eec9ff974edb72f9140b05762fa50907
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>
3358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar#include <media/stagefright/foundation/ColorUtils.h>
3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
3718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
41d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
4207ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h>
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include "include/HevcUtils.h"
4680f78b773f92048944a850efb7b60629643370cdPraveen Chavan#include "include/avc_utils.h"
47dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
48dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false
49dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
50dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif
51dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
5211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \
53dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \
5411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    ALOGW("Condition %s failed "  message, #condition, ##__VA_ARGS__); \
5511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    true; \
5611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih}))
5711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6077e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
611f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32
621f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // filesystem file size
631f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // used by most SD cards
643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
6670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs     = 700000LL;
675b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong
687c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[]    = "com.android.version";
693b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#ifdef SHOW_MODEL_BUILD
703b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[]      = "com.android.model";
717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[]      = "com.android.build";
723b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif
737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
744dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatic const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count";
757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = {
779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = {
829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePrefixSei,
869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSuffixSei,
879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang/* uncomment to include model and build in meta */
897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1
907c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
93b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    Track(MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId);
948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
9837187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
9937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
10025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1023b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
103d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
104b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
1051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
1061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
1079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool isHevc() const { return mIsHevc; }
1081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
1091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
110c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
11170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
112dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
1138b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    static const char *getFourCCForMime(const char *mime);
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
116000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
117000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
1188c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
119000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
120000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    template<class TYPE>
123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity)
125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mEntryCapacity(entryCapacity),
127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mElementCapacity, 0);
131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mEntryCapacity, 0);
1322177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            // Ensure no integer overflow on allocation in add().
1332177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            CHECK_LT(mEntryCapacity, UINT32_MAX / mElementCapacity);
134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
15025f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity);
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            (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value;
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
16925f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            if (pos >= mTotalNumTableEntries * mEntryCapacity) {
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            value = (*it)[(pos % (mElementCapacity * mEntryCapacity))];
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nValues  = mNumValuesInCurrEntry % mEntryCapacity;
192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity];
194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t pos = nEntries * mEntryCapacity + nValues;
199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) {
203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0);
214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK_GT(nEntries, 0);
219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity);
221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries);
224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mEntryCapacity;    // # of values in each entry
235c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mNumValuesInCurrEntry;  // up to mEntryCapacity
237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
247b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    sp<IMediaSource> mSource;
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
249a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
250a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
251eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool mIsHevc;
2541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
2551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
256bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
257c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
25843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
259e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
260d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
266be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
26713aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
269c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
270c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStszTableEntries;
271be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
272c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStcoTableEntries;
273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<off64_t> *mCo64TableEntries;
274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStscTableEntries;
275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStssTableEntries;
276c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mSttsTableEntries;
277c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mCttsTableEntries;
278965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
279000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
280000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
281965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
2833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
2843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
2853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
2863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
2873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
2883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
2893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
2903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
2913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
2923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
2933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
2943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
2953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
298548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
29993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
3023c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
30370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
30470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
30593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
30693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
30725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
308872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
309872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
310872a481558350634a3fd5cb67939de288af00ecbJames Dong
311000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
312000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
31437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
3173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
3183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
3209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
324215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
3259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
3269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
3279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t parseHEVCCodecSpecificData(
3289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            const uint8_t *data, size_t size, HevcParameterSets &paramSets);
3299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
330215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
331faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
33293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
33303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
33419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
33519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
336c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
337c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
338c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
339c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
340c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
341c059860c73678a202bfa33062723e8f82fb779d9James Dong
342690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
343690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
34413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
345690f546b0ee548dbfe997df36418e5302ec2d786James Dong
3461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
3471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
3481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
34979761ab096f57c3027fad9556c2bc436672d614eJames Dong
35079761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
35179761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
352965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
35345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
35445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
35543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
3561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
360b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
363965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
366b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
3679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    void writeHvccBox();
368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
372efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
376efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
37758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    void writeColrBox();
378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
38420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38830ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
389674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
390674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
391de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui      mIsRealTimeRecording(true),
392b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
3931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
394a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
395a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
396a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
397411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
39830ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
39913aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
400e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBuffer(NULL),
401e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBufferOffset(0),
402e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mWriteMoovBoxToMemory(false),
403e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mFreeBoxOffset(0),
404e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStreamableFile(false),
4057837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
4067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang      mMoovExtraSize(0),
40707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
408e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mTimeScale(-1),
409e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStartTimestampUs(-1ll),
41007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
41107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
41286b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
413ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mStartTimeOffsetMs(-1),
414ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mMetaKeys(new AMessage()) {
4157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    addDeviceMeta();
4162aa74dc097fe860abc84769abf2b6e0962718471Robert Shih
4172aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    // Verify mFd is seekable
4182aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    off64_t off = lseek64(mFd, 0, SEEK_SET);
4192aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    if (off < 0) {
4202aa74dc097fe860abc84769abf2b6e0962718471Robert Shih        ALOGE("cannot seek mFd: %s (%d)", strerror(errno), errno);
4212aa74dc097fe860abc84769abf2b6e0962718471Robert Shih        release();
4222aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    }
42330ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
42430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
4268bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
4291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
4311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
4321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
437dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
438dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
439dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
440dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
441dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
442dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
443dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
444dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
445dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
446dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
447dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
448dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
449dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
450dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
451dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
452dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
453dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
454dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
45584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
456dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
457dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
458dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
459dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
460dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
461dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
462dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
463dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
464c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
46513210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
466377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
46713210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
468dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
469dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
470dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
471dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
4728b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static
4738b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
4748b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (mime == NULL) {
4758b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        return NULL;
4768b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
4778b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (!strncasecmp(mime, "audio/", 6)) {
4788b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
4798b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "samr";
4808b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
4818b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "sawb";
4828b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
4838b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4a";
4848b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
4858b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else if (!strncasecmp(mime, "video/", 6)) {
4868b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
4878b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4v";
4888b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
4898b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "s263";
4908b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
4918b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "avc1";
4929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
4939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return "hvc1";
4948b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
4958b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else {
4968b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        ALOGE("Track (%s) other than video or audio is not supported", mime);
4978b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
4988b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    return NULL;
4998b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan}
5008b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan
501b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissenstatus_t MPEG4Writer::addSource(const sp<IMediaSource> &source) {
502bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
503bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
50429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
505bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
506bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
507acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
508acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At most 2 tracks can be supported.
509acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.size() >= 2) {
510a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("Too many tracks (%zu) to add", mTracks.size());
511acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
512acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
513acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
514acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
515acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
516acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
517acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
518acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    bool isAudio = !strncasecmp(mime, "audio/", 6);
5198b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (Track::getFourCCForMime(mime) == NULL) {
5208b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        ALOGE("Unsupported mime '%s'", mime);
521acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
522acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
523acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
524acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At this point, we know the track to be added is either
525acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // video or audio. Thus, we only need to check whether it
526acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // is an audio track or not (if it is not, then it must be
527acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // a video track).
528acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
529acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // No more than one video or one audio track is supported.
530acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    for (List<Track*>::iterator it = mTracks.begin();
531acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong         it != mTracks.end(); ++it) {
532acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        if ((*it)->isAudio() == isAudio) {
533acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            ALOGE("%s track already exists", isAudio? "Audio": "Video");
534acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            return ERROR_UNSUPPORTED;
535acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        }
536acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
537acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
538acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // This is the first track of either audio or video.
539acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
540219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
5422dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
5432dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
547acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
548acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
549acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
550acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
551acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
552a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
553a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
55493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
555a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
556a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
557a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
558a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
559a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
560a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
561a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
562a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
563a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
564a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
565a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
566a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
567a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5687c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
5697c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
5707c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
5717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
5727c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
5737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
5747c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
5757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
5767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
5777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
5787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
5807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
5817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD
5837c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.product.model", val, NULL)
5847c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5857c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Model, val, n + 1);
5867c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
5877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
5897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5907c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
5917c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
5927c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
5947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
5957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
5962dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
5972dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
5982dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
5992dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
6002dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
6012dec2b5be2056c6d9428897dc672185872d30d17James Dong
60278a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
6032dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
60478a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
6052dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
6062dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
6072dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
6082dec2b5be2056c6d9428897dc672185872d30d17James Dong
6092dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
6102dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
6112dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
61278a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
6132dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
6142dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
6152dec2b5be2056c6d9428897dc672185872d30d17James Dong
61678a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
617a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
61878a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
61978a1a286f736888ae7af8860b2c424af0d978848James Dong    }
62078a1a286f736888ae7af8860b2c424af0d978848James Dong
62178a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
62278a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
62378a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
62478a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
62578a1a286f736888ae7af8860b2c424af0d978848James Dong                ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
62678a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
62778a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
62878a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
62978a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
63078a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
63178a1a286f736888ae7af8860b2c424af0d978848James Dong                }
63278a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
63378a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
63478a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
63578a1a286f736888ae7af8860b2c424af0d978848James Dong            }
6362dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
6372dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
63878a1a286f736888ae7af8860b2c424af0d978848James Dong
6392dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
6402dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
6412dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6422dec2b5be2056c6d9428897dc672185872d30d17James Dong
6432dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
6442dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
6452dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
6462dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
6472dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6482dec2b5be2056c6d9428897dc672185872d30d17James Dong
6497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
6507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
6517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
652a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
653a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
6542dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
6552dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
6562dec2b5be2056c6d9428897dc672185872d30d17James Dong}
6572dec2b5be2056c6d9428897dc672185872d30d17James Dong
6582dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
659674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
66025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
663a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
664a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
665a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
666a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
667a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
668a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
669a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
670a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
671a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
672a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
6732dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
6742dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
6752dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
6762dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
6772dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
6782dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6792dec2b5be2056c6d9428897dc672185872d30d17James Dong
6801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
6811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
6821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
6831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
6841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
6851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
6861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
6871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
6881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
689a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
690a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
691d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
692d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
6931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
6941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
6951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
696b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
697b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
698b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
699b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
700b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
7012dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7022dec2b5be2056c6d9428897dc672185872d30d17James Dong
703de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
704de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
705de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
706de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
707de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
708065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
70993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
710a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
711a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
712a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
71393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
714a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
715a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
716a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
717a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
7188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
7198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
7208f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
7218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
72243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
7233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
7248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
72577e8ae9967a078770416619e99ddb5b010def312James Dong    /*
72677e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
72777e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
7287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
7297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
73077e8ae9967a078770416619e99ddb5b010def312James Dong     */
73177e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
73277e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
73377e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
73477e8ae9967a078770416619e99ddb5b010def312James Dong
7357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
7367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
7377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * smaller than the reserved free space at the beginning of a file, AND
7387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * when the content of moov box is constructed. Note that video/audio
7397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * frame data is always written to the file but not in the memory.
7407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
7427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
7437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Moov box needs to be constructed.
7447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
7467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to set to mStreamableFile so that if
7477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the file is intended to be streamable, it is set to true;
7487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * otherwise, it is set to false. When the value is set to false,
7497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * all the content of the moov box is written immediately to
7507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
7517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * content of the moov box is written to an in-memory cache,
7527b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mMoovBoxBuffer, util the following condition happens. Note
7537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
7547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
7557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 2) While the data of the moov box is written to an in-memory
7577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
7587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * If the data size surpasses the reserved space, subsequent moov
7597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * data could no longer be hold in the in-memory cache. This also
7607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
7617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * _all_ moov data must be written to the end of the file.
7627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory must be set to false to direct the write
7637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
7647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 3) If the data size in moov box is smaller than the reserved
7667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space after moov box is completely constructed, the in-memory
7677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache copy of the moov box is written to the reserved free
7687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space. Thus, immediately after the moov is completedly
7697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * constructed, mWriteMoovBoxToMemory is always set to false.
7707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
7717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = false;
7727837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
7737837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
7747837c17063a4c50bc856ba59418516fdab731de7James Dong
775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7777837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7797837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
7802dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
7812dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
7822dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
7832dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
7842dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
7857837c17063a4c50bc856ba59418516fdab731de7James Dong    }
78643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
78777e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
78877e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
78977e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
79077e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
79177e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
79277e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
79377e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
79477e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
79577e8ae9967a078770416619e99ddb5b010def312James Dong    }
7967837c17063a4c50bc856ba59418516fdab731de7James Dong
7977837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
798c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
7991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
8001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
8011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
8021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
8031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
8041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
8061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
8071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
8081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
811a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
812a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
8141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
815a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
81625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
8201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
8211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
82337187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
824674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
82537187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
826a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
827a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
82837187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
829a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
830a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
83137187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
83237187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
83337187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
83437187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
835a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
83637187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
837a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
838a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
8391c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
840b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
841411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
842411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
843411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
8441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
8461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
8471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
8491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
8501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
8531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
854411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
855b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
8561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
85813f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
85913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
86013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
86113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
86213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
86313f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
86413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
86513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
86613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
86713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
86813f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
86913f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
8703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
87113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
87213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
87313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
87413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
87513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
87613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
87713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
87813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
87913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
88013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
88113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
88213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
88313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
88413f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
88513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
88613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
88713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
88813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
88913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
89013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
89113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
89213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
89313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
89413f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
89513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
89613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
89713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
89813f6284305e4b27395a23db7882d670bdb1bcae1James Dong
89913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
90013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
90113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
90213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
90313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
90413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
90513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
90613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
90713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
90813f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
90913f6284305e4b27395a23db7882d670bdb1bcae1James Dong
910411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
911411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
912411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
913411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
914411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
9154c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    free(mMoovBoxBuffer);
9164c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    mMoovBoxBuffer = NULL;
917411ba422e3635d534928ffd81abf54f4f291c739James Dong}
91813f6284305e4b27395a23db7882d670bdb1bcae1James Dong
9198bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() {
920674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
92137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
922411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
923411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
924411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
925411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
926411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
927411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
928411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
929411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
930411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
9348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
93565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
93620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
93720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
93837187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
93937187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
94037187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
94137187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
9448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
9458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
94620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
94765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
94865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
94965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
95065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
95165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
95265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
953a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
95465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
9587837c17063a4c50bc856ba59418516fdab731de7James Dong
95937187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
96037187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
961411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
96237187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
96337187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
96437187916a486504acaf83bea30147eb5fbf46ae5James Dong
96520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
9661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
967c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
9681f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
969c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
9701acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
971c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
9721f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
9731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
974c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
9751acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
976c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Construct moov box now
9797837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
9807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = mStreamableFile;
9817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
9827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
9837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // for moov box if the file is not streamable.
9847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
9857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
9867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        CHECK(mMoovBoxBuffer != NULL);
9877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
98920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // mWriteMoovBoxToMemory could be set to false in
9917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // MPEG4Writer::write() method
9927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
9937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mWriteMoovBoxToMemory = false;
9947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // Content of the moov box is saved in the cache, and the in-memory
9957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // moov box needs to be written to the file in a single shot.
9967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
99743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
9987837c17063a4c50bc856ba59418516fdab731de7James Dong
9997837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
1000c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
10017837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
1002674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
10037837c17063a4c50bc856ba59418516fdab731de7James Dong
10047837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
1005c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
10067837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
10077837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
10087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    } else {
10097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        ALOGI("The mp4 file will not be streamable.");
10107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
10117837c17063a4c50bc856ba59418516fdab731de7James Dong
10127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Free in-memory cache for moov box
10137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mMoovBoxBuffer != NULL) {
10147837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
10157837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
10167837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
10177837c17063a4c50bc856ba59418516fdab731de7James Dong    }
10187837c17063a4c50bc856ba59418516fdab731de7James Dong
10190c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
102020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1021411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
102237187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1025efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
1026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
1027efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
1028efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
1029efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
10302b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
10312b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
10322b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen        return 0;
10332b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    }
10342b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    uint32_t mpeg4Time = uint32_t(now) + delta;
1035efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
1036efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
1037efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
1038efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
1039efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
1040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
1041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
1042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
1043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
1044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
1045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
1047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
1048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
1049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
1050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
1053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
1060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
1061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
1064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
1065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
106607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
106707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
106807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1069e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeMetaBox();
1070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
1071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
1073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
1074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
10782cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
1083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
1084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
10858284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
10868284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
10878284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1088b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
10898284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
10908284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1091b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
10928284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
1093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1094b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
109807ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
109907ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
110007ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
110107ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
110207ec01904613a0bac32caaa8444b4690998faed7James Dong
110307ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
110407ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
110507ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
110607ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
110707ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
110807ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
110907ec01904613a0bac32caaa8444b4690998faed7James Dong    }
111007ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
111107ec01904613a0bac32caaa8444b4690998faed7James Dong}
111207ec01904613a0bac32caaa8444b4690998faed7James Dong
111370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
111407ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
111507ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
111607ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
111707ec01904613a0bac32caaa8444b4690998faed7James Dong    }
111807ec01904613a0bac32caaa8444b4690998faed7James Dong
111970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
112070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
112170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
112270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
112370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
112470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
112570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
112670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
112770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
112813aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
112913aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
113013aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
113113aec890216948b0c364f8f92792129d0335f506James Dong}
113213aec890216948b0c364f8f92792129d0335f506James Dong
113313aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
113413aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
113513aec890216948b0c364f8f92792129d0335f506James Dong}
113613aec890216948b0c364f8f92792129d0335f506James Dong
113713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
113813aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
113913aec890216948b0c364f8f92792129d0335f506James Dong}
114020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1141c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1142c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1144c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
1145c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
1146c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
114720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
114820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
114920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
115120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
115220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
115403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
115503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
115603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
115703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
115803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
115903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
116003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
116103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
116203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
116303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
116403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
116503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
116603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
116780f78b773f92048944a850efb7b60629643370cdPraveen Chavanoff64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) {
116880f78b773f92048944a850efb7b60629643370cdPraveen Chavan    off64_t old_offset = mOffset;
116980f78b773f92048944a850efb7b60629643370cdPraveen Chavan
117080f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs
117180f78b773f92048944a850efb7b60629643370cdPraveen Chavan
117280f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset();
117380f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *currentNalStart = dataStart;
117480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *nextNalStart;
117580f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *data = dataStart;
117680f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t nextNalSize;
117780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ?
117880f78b773f92048944a850efb7b60629643370cdPraveen Chavan                   kExtensionNALSearchRange : buffer->range_length();
117980f78b773f92048944a850efb7b60629643370cdPraveen Chavan
118080f78b773f92048944a850efb7b60629643370cdPraveen Chavan    while (getNextNALUnit(&data, &searchSize, &nextNalStart,
118180f78b773f92048944a850efb7b60629643370cdPraveen Chavan            &nextNalSize, true) == OK) {
118210cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar        size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */;
118380f78b773f92048944a850efb7b60629643370cdPraveen Chavan        MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize);
118480f78b773f92048944a850efb7b60629643370cdPraveen Chavan        addLengthPrefixedSample_l(nalBuf);
118580f78b773f92048944a850efb7b60629643370cdPraveen Chavan        nalBuf->release();
118680f78b773f92048944a850efb7b60629643370cdPraveen Chavan
118780f78b773f92048944a850efb7b60629643370cdPraveen Chavan        currentNalStart = nextNalStart;
118880f78b773f92048944a850efb7b60629643370cdPraveen Chavan    }
118980f78b773f92048944a850efb7b60629643370cdPraveen Chavan
119080f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t currentNalOffset = currentNalStart - dataStart;
119180f78b773f92048944a850efb7b60629643370cdPraveen Chavan    buffer->set_range(buffer->range_offset() + currentNalOffset,
119280f78b773f92048944a850efb7b60629643370cdPraveen Chavan            buffer->range_length() - currentNalOffset);
119380f78b773f92048944a850efb7b60629643370cdPraveen Chavan    addLengthPrefixedSample_l(buffer);
119480f78b773f92048944a850efb7b60629643370cdPraveen Chavan
119580f78b773f92048944a850efb7b60629643370cdPraveen Chavan    return old_offset;
119680f78b773f92048944a850efb7b60629643370cdPraveen Chavan}
119780f78b773f92048944a850efb7b60629643370cdPraveen Chavan
1198c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1199c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
120030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
120130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
120203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1203b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1204b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1205c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1206b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1207c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1208b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1209c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1210b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1211c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1212c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1213c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1214c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1215c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1216b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1217b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1218b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
121943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
122030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1221b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1222c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1223b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1224c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1225c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1226b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1227b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
122830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
122930ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
123030ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
123130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
12327837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1233674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
12347837c17063a4c50bc856ba59418516fdab731de7James Dong
12357837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
12367837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
12377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1238c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
12391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
12407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // The reserved moov box at the beginning of the file
12417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // is not big enough. Moov box should be written to
12427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the end of the file from now on, but not to the
12437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // in-memory cache.
12447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
12457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // We write partial moov box that is in the memory to
12467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the file first.
1247c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
12487837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
12497837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
12507837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1251674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1252674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
12537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
12547837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
12557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
12567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // All subsequent moov box content will be written
12577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // to the end of the file.
12587837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
12597837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
12607837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
12617837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
12627837c17063a4c50bc856ba59418516fdab731de7James Dong        }
12637837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1264674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
12657837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
12667837c17063a4c50bc856ba59418516fdab731de7James Dong    }
12677837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
12687837c17063a4c50bc856ba59418516fdab731de7James Dong}
12697837c17063a4c50bc856ba59418516fdab731de7James Dong
1270e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1271e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mBoxes.push_back(mWriteMoovBoxToMemory?
1272e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mMoovBoxBufferOffset: mOffset);
1273e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1274e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1275e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1276e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1277e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
12790c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12817837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
12827837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
128320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
12890c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1291c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12947837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
12957837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
12967837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
12977837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1298c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
12997837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
13007837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1301c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
13027837c17063a4c50bc856ba59418516fdab731de7James Dong    }
130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1306674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
131020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1311674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
131520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1316674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1321674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1326674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
13300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
1331674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
133507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
133607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
133707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
133807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
133907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
134007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
134107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
134207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
134307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
134407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
134507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
134607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
134707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
134807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
134907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
135007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
135107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
135207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
135307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
135407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
135507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
135607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
135707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
135807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
135907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
136007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
136107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
136207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
136307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
136407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
136507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
136607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
136707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
136807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
136907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
137007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
137107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
137207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
137307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
137407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
137507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
137607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
137707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
137807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
137907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
138007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
138107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
138207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
138307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
138407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
138507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
138607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
138707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
138807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
138907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
139007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
139107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
139207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
139307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
139407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
139507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
139607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
139707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
139807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
139907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
140007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
140107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
14027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
140307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
140407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
140507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1406e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1407e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1408e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1409e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1410e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
14127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
14137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1414e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1415e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1416e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
14174dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) {
14184dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 9) {
14194dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        return BAD_VALUE;
14204dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
14214dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
14224dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 0) {
14234dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount);
14244dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32;
14254dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
14264dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
14274dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    return OK;
14284dbff11975e737482537e1636051690188f3fbc4Praveen Chavan}
14294dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1431674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
143220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
143478a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
143578a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
143678a1a286f736888ae7af8860b2c424af0d978848James Dong}
143778a1a286f736888ae7af8860b2c424af0d978848James Dong
1438d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1439d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1440d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1441d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1442d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1443d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1444956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1445d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1446d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1447d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1448d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
14491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
145077e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
145177e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
145277e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
145377e8ae9967a078770416619e99ddb5b010def312James Dong    }
1454acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1455acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1456acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1457acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1458d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1459d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1460d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1461d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1462d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1463d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1464d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1465d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1466d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1467d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1468d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1469d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1470d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1471d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1472d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1473d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1474d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
147525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
147625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
147725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
147825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
147925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
148025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
148125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
148225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
148325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
148425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
148525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
148625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
148725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1488f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1489a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
149043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
14913c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1492065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1493f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1494a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
14953c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
14963c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
14973c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1498f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
14993c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
15003c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
15013c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
15023c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
150358ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
150458ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
150558ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
150658ae9c530247668f8af36e30d228c716c226b3d4James Dong}
150758ae9c530247668f8af36e30d228c716c226b3d4James Dong
150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
150920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1511b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId)
151220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
151325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
151420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
151520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1516a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1517a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1518eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1519bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1520c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1521956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1522be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1523c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1524c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1525c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)),
1526c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)),
1527c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1528c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
1529c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
153125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1532548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
153313f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
153413f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
153519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
15368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
15371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
15381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
15391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
15409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
15411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
15421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
15431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
15441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1545c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1546c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1547c059860c73678a202bfa33062723e8f82fb779d9James Dong
15481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
15491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1550c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1551c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1552c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1553c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1554c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
15551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
155678a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
155778a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
155878a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
155978a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1560c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1561c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1562c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1563c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
156478a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
156578a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
156678a1a286f736888ae7af8860b2c424af0d978848James Dong    }
15671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
15701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
15711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1572c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1573c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1574c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
15751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1578c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
15791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
158279761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
15831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15845a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1585377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
15865a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1587c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1588c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
15891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1591965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1592965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1593965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1594965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1595965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1596965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1597c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1598c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1599965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1600965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1601c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1602c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1603c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1604c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1605c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1606c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1607c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
16081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
16091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1610c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
16113856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1612c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1613c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1614c059860c73678a202bfa33062723e8f82fb779d9James Dong
1615c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1616c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1617c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1618c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1619c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1620c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1621c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1622c059860c73678a202bfa33062723e8f82fb779d9James Dong
1623c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1624c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1625c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1626c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1627c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1628c059860c73678a202bfa33062723e8f82fb779d9James Dong
162943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
163019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
163119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
163219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
163319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
163419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
163519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
16369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint32_t type;
16379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const void *data = NULL;
16389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t size = 0;
163919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
16409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyAVCC, &type, &data, &size);
16419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
16429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyHVCC, &type, &data, &size);
164319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
164419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
164519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
164619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
16479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (esds.getCodecSpecificInfo(&data, &size) != OK) {
16489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                data = NULL;
16499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                size = 0;
165019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
165119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
165219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
16539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
16549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mGotAllCodecSpecificData = true;
16559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
165620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
165720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
165820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
165920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
166020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1661c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1662c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1663c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1664c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1665c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1666c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1667c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1668c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1669c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1670c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1671c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1672c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1673c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1674c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1675c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1676c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
167720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
167820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
167920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
168020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
168120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
168220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
168393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
16843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
168593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
168693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
168793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
168893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
168993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
169093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1691a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
169293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
169393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
169493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
169593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
169693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
169793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
16981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
16991c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
17003856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
17011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
17021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
17031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
17041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17061c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
17073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
17081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
17091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
17101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
17131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
17151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
17161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
17171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
17181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
172143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
17221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1724fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1725a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
17265410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1727fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1728fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1729fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1730fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1731fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
17329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
173380f78b773f92048944a850efb7b60629643370cdPraveen Chavan                                ? addMultipleLengthPrefixedSamples_l(*it)
1734fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1735fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1736fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1737fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1738fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
17391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
17421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1743fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
17441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1745fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
17461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1748fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
17493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
17501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
175170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
175270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1753e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
175470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
17551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
175670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
175770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
175870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
17591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1760377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
17611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1763fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
17643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
17651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
17671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
17681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
17701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
17711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
17721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
17731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
17751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
17761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
17803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1781fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
17821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
17851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
17861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1787fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
17881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
17901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1791fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1792fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1793fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
179470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
179570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
179670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
179770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
179870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
179970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
180070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1801fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
18021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
18031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1804fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1805fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
18061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18081c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
18093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
18101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1811a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1812fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1813fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
18141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1815fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1816fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1817fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1818fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
18191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
18201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
18211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1822de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
1823de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
1824de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
1825de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
1826fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1827de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1828de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
1829de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1830fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1831de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1832de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
1833de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1834fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
18351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1836fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1837fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
18381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18401c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
18413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
18421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
18441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1845e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
18461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
18471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
18481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
18491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
185070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
185170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
18521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
18531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
18541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
18561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
18571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
18581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
18591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1860411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
18611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
18621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
186593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1866a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1867a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1868a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1869a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1870a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
187125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
187293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
187319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
187419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
187519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
187670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
187719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
187813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
187913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
188013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
188113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
188213f6284305e4b27395a23db7882d670bdb1bcae1James Dong
188393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
188493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1885f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1886de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
1887a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1888a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1889a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1890a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1891a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1892a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
189386b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
189486b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1895a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
189686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
189786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
189886b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
189986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
190086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1901a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
1902a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1903a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1904f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1905a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1906f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
190725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
190825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
190925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
191025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
191120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
191220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
191320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
191420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
191520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
191620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1917eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1918c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
191925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1920956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
19211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
192243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
192320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
192425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
192520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
192625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
192725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
192820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
192920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
193037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1931a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
193237187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1933a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1934a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
193537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
193672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track stopping", mIsAudio? "Audio": "Video");
1937eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
193829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1939eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1940eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1941eaae38445a340c4857c1c5569475879a728e63b7James Dong
194220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
194337187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
194420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
194520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
194620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
194772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopping", mIsAudio? "Audio": "Video");
194872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSource->stop();
194972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopped", mIsAudio? "Audio": "Video");
195072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
195120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
195220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
1953377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
195437187916a486504acaf83bea30147eb5fbf46ae5James Dong
1955b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
195637187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
195720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
195820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
195925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
196025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
196125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
196225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
196320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
196420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
196520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
196620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
196737187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
1968377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
196920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
197020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
19723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
19733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
19753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
19763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
19793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
19803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
19823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
19833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
19843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
198547d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar    const uint8_t *nextStartCode = findNextNalStartCode(data, length);
19863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
19873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
198829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
19893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
19903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
19933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
19943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
199529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
19963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
19973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
19993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
20003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
20013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
20033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
20053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
200607b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                // COULD DO: set profile/level to the lowest required to support all SPSs
200729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
20123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
20163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
20193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
20203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
20233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
20249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 4 + 7);
20259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
20269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
20279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
20289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
20299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("copyHEVCCodecSpecificData");
20309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
20319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
20329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 23);
20339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
20349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
20359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData(
20369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, size_t minLength) {
20379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < minLength) {
2038377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
20439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
20449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
20459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
20469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
20479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = size;
20483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
20493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
20503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
20513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
20533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
20543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20553856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
20563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
20573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
20583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
20593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
20603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
20613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
20623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
20633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
20643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
20653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
20663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
20673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
20683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
20693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
20703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
207129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
20723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
20733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
20753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
20763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
20783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
20793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
208029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
20813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
20823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
20843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
20853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
20873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
208829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
20933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
20973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
20983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
20993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
21003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
21033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
21043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
21053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
210629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
21073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
2111377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
21123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
21173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
21183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
21193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
212029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
21213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2124377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
21253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
21263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21281374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
21291374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
21301374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
21311374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
21323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
21333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
21343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
21353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
21363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
213729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
21383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
21393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
21403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21411374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
21423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
21433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2144548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
214503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
214603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2147548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
214803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
214929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
215003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
215103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
215203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2154377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
215503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
215603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
215703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
21593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
21603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
216103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
216203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
216403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
216503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
216603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
21683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
216903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
21709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
21719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
21729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
21739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
21749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
217503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
21763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
21773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
21783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
21793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
218003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2182b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2183b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2184b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2185b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2186b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
218703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
21893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
21903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
21913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
21923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
21933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
21943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
21953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
21963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
21973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
21983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
22003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
22013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
22023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
22033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
22053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
22063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
22073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
22083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
22093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
22103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
22113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
22123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
22133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
22143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
22153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
22163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
22173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
22183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
221903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
222003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
222103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
222203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
22239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
22259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, HevcParameterSets &paramSets) {
22269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("parseHEVCCodecSpecificData");
22289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *tmp = data;
22299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *nextStartCode = data;
22309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t bytesLeft = size;
22319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
223247d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar        nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4);
22339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
22349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (err != OK) {
22359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Move on to find the next parameter set
22399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        bytesLeft -= nextStartCode - tmp;
22409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        tmp = nextStartCode;
22419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t csdSize = 23;
22449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const size_t numNalUnits = paramSets.getNumNalUnits();
22459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
22469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kMandatoryHevcNalUnitTypes[i];
22479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
22489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets == 0) {
22499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Cound not find NAL unit of type %d", type);
22509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
22549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kHevcNalUnitTypes[i];
22559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
22569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets > 0xffff) {
22579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
22589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        csdSize += 3;
22619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (size_t j = 0; j < numNalUnits; ++j) {
22629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (paramSets.getType(j) != type) {
22639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                continue;
22649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
22659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            csdSize += 2 + paramSets.getSize(j);
22669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = csdSize;
22699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
22709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
22719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
22739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
22749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData != NULL) {
22769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Already have codec specific data");
22779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
22789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < 4) {
22819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Codec specific data length too short: %zu", size);
22829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
22839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Data is in the form of HEVCCodecSpecificData
22869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (memcmp("\x00\x00\x00\x01", data, 4)) {
22879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return copyHEVCCodecSpecificData(data, size);
22889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    HevcParameterSets paramSets;
22919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
22923d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed parsing codec specific data");
22939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
22949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificData = malloc(mCodecSpecificDataSize);
22979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
22989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
22999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
23009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
23019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
23033d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim            &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2);
23049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (err != OK) {
23053d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed constructing HVCC atom");
23069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return err;
23079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
23089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
23099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
23109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
23119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
2312872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2313872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2314872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2315872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2316872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2317872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2318872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2319872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2320872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2321872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2322872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2323872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2324872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2325872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2326872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2327872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2328872a481558350634a3fd5cb67939de288af00ecbJames Dong
232937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
233030ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
233113aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
233243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
233313aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
233413aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
23357c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar    int32_t nActualFrames = 0;        // frames containing non-CSD data (non-0 length)
233613aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2337965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2338965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2339965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2340965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2341965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2342000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2343a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2344965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2345000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2346000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2347000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
234843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2349c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2350e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2351a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2352a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
2353a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
2354a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
2355a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2356de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2357de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2358de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2359de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2360985f838934510983d8a887461e98dca60a6e858fJames Dong
2361d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
236220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
236393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
236420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
236511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    const char *trackName = mIsAudio ? "Audio" : "Video";
236693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
236720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
236820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
236920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
237013aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
237120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
237220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
237320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2374a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2375a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2376a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2377a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2378a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2379a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2380a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2381a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2382a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
238330ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
238430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
238503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
238603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
238703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
23887c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // if config format (at track addition) already had CSD, keep that
23897c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // UNLESS we have not received any frames yet.
23907c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // TODO: for now the entire CSD has to come in one frame for encoders, even though
23917c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // they need to be spread out for decoders.
23927c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            if (mGotAllCodecSpecificData && nActualFrames > 0) {
23937c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                ALOGI("ignoring additional CSD for video track after first frame");
23947c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            } else {
23957c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                mMeta = mSource->getFormat(); // get output format after format change
23967c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
23977c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                if (mIsAvc) {
23987c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    status_t err = makeAVCCodecSpecificData(
23997c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
24007c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
24017c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
24027c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    CHECK_EQ((status_t)OK, err);
24037c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsHevc) {
24047c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    status_t err = makeHEVCCodecSpecificData(
24057c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
24067c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
24077c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
24087c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    CHECK_EQ((status_t)OK, err);
24097c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsMPEG4) {
24107c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
24117c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
24127c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                }
241330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
241430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
241530ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
241630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
241730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2418548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
241930ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2420a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2421a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
24227c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar        ++nActualFrames;
24237c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
2424d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2425d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2426d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2427d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2428d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2429d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2430d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2431d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2432d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2433d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
24349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) StripStartcode(copy);
2435e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2436b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
24379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) {
2438b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2439b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2440b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2441b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2442b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2443b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2444050b28a593350047845a45a14cc5026221ac1620James Dong
2445d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
24461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
24471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
24481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2449d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2450316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
2451316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileSizeLimitBytes);
2452d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2453d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2454d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2455d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2456316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
2457316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileDurationLimitUs);
2458d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2459d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2460d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2461d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2462050b28a593350047845a45a14cc5026221ac1620James Dong
2463d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2464d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2465d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2466d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2467d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2468c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
246970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2470f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2471f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
24728428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
24733c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
247448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2475a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
24768428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
247711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
247811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
247911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
248011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
248111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
24828428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
248311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
248411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
248511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
248611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
248711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
24888428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2489a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2490a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2491a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2492a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
249311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
249411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
249511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
249611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
249711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2498000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        if (!mIsAudio) {
2499965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2500965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2501965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2502000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2503965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2504965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2505965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2506965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2507000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2508000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
250911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
251011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
251111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
251211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
251311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2514965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2515a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2516000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2517000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2518000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2519000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2520000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
252111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
252211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
252311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
252411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
252511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2526c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
252743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
252843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
252943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
253043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
253143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
253243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
253343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
253443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
253543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
253643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
253743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
253843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
253943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
254043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
254143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2542000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2543000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2544c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2545000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2546000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2547000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2548000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2549000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2550000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2551000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2552000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2553000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2554000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2555965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2556872a481558350634a3fd5cb67939de288af00ecbJames Dong
2557de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        if (mOwner->isRealTimeRecording()) {
2558872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2559872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2560e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2561e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2562872a481558350634a3fd5cb67939de288af00ecbJames Dong
256311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
256411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
256511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
256611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
256711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2568a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
256911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, previousPausedDurationUs);
2570c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2571c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
25723b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
25733b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
25745a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
25755a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
25765a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
25775a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
25785a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
25795a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
25805a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
25815a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2582c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2583f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang            ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
2584f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang                    (long long)timestampUs, (long long)lastTimestampUs, trackName);
258511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
25860332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang            mSource->stop();
2587c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return UNKNOWN_ERROR;
25888c460498c028888c533ab442be12b6d4b669b965James Dong        }
25898c460498c028888c533ab442be12b6d4b669b965James Dong
259085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // if the duration is different for this sample, see if it is close enough to the previous
259185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // duration that we can fudge it and use the same value, to avoid filling the stts table
259285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // with lots of near-identical entries.
259385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // "close enough" here means that the current duration needs to be adjusted by less
259485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // than 0.1 milliseconds
259585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
259685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
259785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                    + (mTimeScale / 2)) / mTimeScale;
259885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            if (deltaUs > -100 && deltaUs < 100) {
259985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // use previous ticks, and adjust timestamp as if it was actually that number
260085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // of ticks
260185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                currDurationTicks = lastDurationTicks;
260285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                timestampUs += deltaUs;
260385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
260485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        }
260585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen
2606c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2607c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2608c059860c73678a202bfa33062723e8f82fb779d9James Dong
2609a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2610a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2611c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
261279761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2613be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2614be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2615be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2616be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2617965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2618be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2619be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2620c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2621be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2622be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
26238644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2624be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2625a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
262611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, lastTimestampUs);
26278644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2628c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
26298644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
263020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2631d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2632c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2633d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2634d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
263593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
263693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
263793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
263893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2639faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
264093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
264143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
264280f78b773f92048944a850efb7b60629643370cdPraveen Chavan            off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy)
264358ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2644c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2645c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2646c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2647c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2648c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2649c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
26501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
265158ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
265258ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
265358ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
265458ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
265558ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
265613aec890216948b0c364f8f92792129d0335f506James Dong
265713aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
265813aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
26591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
26601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
266113aec890216948b0c364f8f92792129d0335f506James Dong        } else {
266213aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
266313aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
266413aec890216948b0c364f8f92792129d0335f506James Dong            } else {
266543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
266643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
266743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
266843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
266943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
267013aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
267113aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2672c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2673c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2674c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
267513aec890216948b0c364f8f92792129d0335f506James Dong                    }
26761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
267713aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
267813aec890216948b0c364f8f92792129d0335f506James Dong                }
267913aec890216948b0c364f8f92792129d0335f506James Dong            }
268013aec890216948b0c364f8f92792129d0335f506James Dong        }
268113aec890216948b0c364f8f92792129d0335f506James Dong
268220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
268325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
268445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2685690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2686f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
268745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2688bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2689be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
269013aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
269143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2692c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
269358ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
26941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
26951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
269613aec890216948b0c364f8f92792129d0335f506James Dong    }
269713aec890216948b0c364f8f92792129d0335f506James Dong
2698be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2699be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2700be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2701c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
27028f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
270379761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2704be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2705be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2706be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2707a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2708c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
270979761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2710a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
271179761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2712a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2713a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
271479761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2715a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2716a472613aec322e25891abf5c77bf3f7e3c244920James Dong
271743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
271843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
271943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
272043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
272143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
272243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
272343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
272443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2725c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
272625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
272743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
272843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
272943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2730df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
273111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
2732872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2733a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
2734872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2735365a963142093a1cd8efdcea76b5f65096a5b115James Dong
273637187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
273737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
273837187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
273937187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2740365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2741365a963142093a1cd8efdcea76b5f65096a5b115James Dong
274245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
2743c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
274429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
274545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
274645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
274745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2748c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (!mIsAudio && mStssTableEntries->count() == 0) {  // no sync frames for video
274929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
275045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
275145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
275245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
275345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
275445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
275545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
275645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
275745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
275845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
275945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
276043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
276107ec01904613a0bac32caaa8444b4690998faed7James Dong
276207ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
276307ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
276407ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
276507ec01904613a0bac32caaa8444b4690998faed7James Dong    }
276607ec01904613a0bac32caaa8444b4690998faed7James Dong
276743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
276843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
276943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
277043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
277143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
277243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
277343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
277443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
277543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
277643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
277743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
277843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2779c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
278043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
278186b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
278286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
278386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
278486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
278586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
278686b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
278786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
278886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
278986b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
279086b7f47aa7482424cf8fd248f1315311919be3b0James Dong
279186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
279270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
279370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
279486b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
279570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
279607ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
279707ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
279807ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
279907ec01904613a0bac32caaa8444b4690998faed7James Dong
280043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
280143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
280243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
280343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
280470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
280570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
280670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
280770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
280870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
280970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
281070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
281170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
281243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
281343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
281443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2815faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
2816a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
2817c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2818215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2819215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
2820a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
2821bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
282293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
282393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
282493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
282593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2826faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2827bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2828faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2829bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2830faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2831faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2832faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2833faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2834bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2835bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2836faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2837faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2838faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2839faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2840faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2841faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2842bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2843bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2844faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2845faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2846faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2847bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2848bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2849faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2850faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2851faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2852faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2853d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
2854a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
2855e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2856d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2857e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2858e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2859e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
2860a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
2861e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2862e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2863e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2864e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2865de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
2866de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
2867de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
2868de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2869b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2870b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2871b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2872b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
28731c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
28743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
28751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
28761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
28771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
287813aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
287920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
288020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28813b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2882c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
288320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
288420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2885d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2886d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2887d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2888d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2889690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2890690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2891690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2892690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2893690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
28949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
28959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
2896690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2897690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
289829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2899690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2900690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2901690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2902690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2903690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
290429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2905690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2906690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2907690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2908690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2909690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2910690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
291220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29133856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
29141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
29158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
2916efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
2937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
2938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
2939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
2940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
2942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
2946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
2947965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
2948b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
2955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
29618b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
29628b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
296329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
29678b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    mOwner->beginBox(fourcc);        // video format
2968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
2971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
2978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
2979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
2980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
2983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
2984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
2985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
2986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
2988c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
2989c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
2990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
2991b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
2992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
299343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(23 + mCodecSpecificDataSize, 128);
2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
30019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
30029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        writeHvccBox();
3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
300658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    writeColrBox();
3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
301058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() {
301158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    ColorAspects aspects;
301258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    memset(&aspects, 0, sizeof(aspects));
301358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    // TRICKY: using | instead of || because we want to execute all findInt32-s
301458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
301558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
301658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
301758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
301858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t primaries, transfer, coeffs;
301958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        bool fullRange;
302058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorUtils::convertCodecColorAspectsToIsoAspects(
302158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                aspects, &primaries, &transfer, &coeffs, &fullRange);
302258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->beginBox("colr");
302358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeFourcc("nclx");
302458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(primaries);
302558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(transfer);
302658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(coeffs);
302758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt8(fullRange ? 128 : 0);
302858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->endBox(); // colr
302958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
303058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar}
303158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
30368b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
30378b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
303829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
3039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
3040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
3043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
3046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
3049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
3050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
3051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
3052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
3057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
3060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
3061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
3062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
3063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
3064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
3069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
307143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
307443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
3075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
3077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
3078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
3080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
3081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
3083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
3085b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
3086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3087b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
308846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt8(0x00);   // buffer size 24-bit (0x300)
308946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
309096bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
309146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
309296bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
309346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
309446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
309546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
3096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
3098b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3099b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3100b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3104b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3105b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3106b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3111b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
3112b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
311343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
3114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3115b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3116b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
3117b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3118b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
3119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3120b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
3121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
3122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3123b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
3124b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3125b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
3126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
3127b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
312946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        0x01, 0x77, 0x00, // buffer size 96000 bytes
3130b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
3132b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
313396bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
313446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
313596bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
313646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
313746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
313846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
313946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
3140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
3141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3145b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3147b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3149b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3150b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3151b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3152b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3153b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3154b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3155efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
3156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
3157b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
3158b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
3159b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
3160b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3162219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
3163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
31648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
3165b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
3166b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
3167b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
3168b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
3169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3170b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3171b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
3172b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
3173b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
3174b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
3175b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3176b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
317720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3178b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
3179b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3180b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3181b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
3182b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
3183b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
3184b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
3185b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
3186b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3187b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
3188b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
3189b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3190b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
3191b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3192b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3193b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
3194b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
3195b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
3196b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
3197b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
3198b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3199b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3200b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3201b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3202b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3203b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
3204b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
3205b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
3206b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
3207b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3208b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3209b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3210b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3211b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
3212b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
3213b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
3215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
3216b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3218b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
3220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
3221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3224efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
3226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
3227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
3231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
3233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
3234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
3235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
3236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
3237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
3238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // language code
3239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
3240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3243b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
3244b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
3245b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
3246b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
3247b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
3248b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
3249b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
3250b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
3251b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3252b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3253b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3254b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
3255b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
3256b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
3257b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
3258b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3259b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
3260b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3261b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3262b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
3263b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
3264b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3265b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
3266b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
3267b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
3268b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3269b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3270b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
3271b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
3272b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
3273b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
3274b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3275b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3276b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
3277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
327843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
3279b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
3281b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
3282b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3283b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3284b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
3285b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3286b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
3287b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3288b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
32899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
32909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() {
32919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK(mCodecSpecificData);
32929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK_GE(mCodecSpecificDataSize, 5);
32939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
32949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Patch avcc's lengthSize field to match the number
32959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // of bytes we use to indicate the size of a nal unit.
32969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
32979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
32989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->beginBox("hvcC");
32999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
33009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->endBox();  // hvcC
33019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
33029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
3303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
3304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
3305b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
3306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
3307b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
3308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
3309b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
3310b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3311b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3312b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
3313b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
3314b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3318b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3319b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3320000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3321a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
332443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3327000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
3328000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3329000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3330000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3331000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3332000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3333c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3334c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
3335c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
3336c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3337c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
3338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
3339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
334020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3341965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
3342965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
3343965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3344965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3345965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3346000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
3347000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3348000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
3349000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
3350000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3351965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
3352c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
3353965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3354965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3355965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3356a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3357c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3358965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3359965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
3360000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3361c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3362c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mCttsTableEntries->get(duration, 1));
3363c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back host byte order
3364c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1);
3365c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
3366965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
3367965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
3368965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
3370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
3371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3372c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
3373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
3374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
337525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
3376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
3377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
3378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3379c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
3380c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
3381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
3382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
338320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
3385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
3386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3387c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
3388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
3389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
339020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
3393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3394c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
3395c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
3396c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
3397c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
3398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
340020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
340120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
340207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
340307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
340407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
340507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
340607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
340707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
3408e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() {
3409e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
3410e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
3411e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
3412e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeFourcc("mdta");
3413e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
3414e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
3415e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
3416e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
3417e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3418e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3419e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3420e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
3421e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3422e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3423e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
3424e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
3425e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
3426e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3427e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3428e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3429e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
3430e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
3431e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
3432e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
3433e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3434e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3435e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3436e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3437e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
3438e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3439e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3440e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
3441e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3442e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
3443e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
3444e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3445e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3446e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
34477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
34487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
34497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
34507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
34517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
34527c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
34537c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
34547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
34557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
34567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
3457e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
3458e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3459e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
3460e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
34617c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
34627c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3463e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
3464e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3465e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3466e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3467e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
3468e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3469e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
3470e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
34717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
34727c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3473e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
3474e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3475e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3476e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3477e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
3478e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3479e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
34807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
34817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3482e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
3483e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3484e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3485e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
3486e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
3487e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
3488e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3489e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
3490e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3491e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3492e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() {
3493e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3494e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
3495e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
3496e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3497e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3498e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
3499e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeHdlr();
3500e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
3501e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
3502e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3503e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3504e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
350507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
350607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
350707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
350807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
350907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
351007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
351107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
351207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
351307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
3514432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
3515432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
351607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
351707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
351807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
351907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
352007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
352107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
352207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
352307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
352420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3525