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"
46dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
47dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false
48dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
49dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif
50dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
5111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \
52dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \
5311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    ALOGW("Condition %s failed "  message, #condition, ##__VA_ARGS__); \
5411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    true; \
5511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih}))
5611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5977e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
601f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32
611f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // filesystem file size
621f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // used by most SD cards
633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
6570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs     = 700000LL;
665b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong
677c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[]    = "com.android.version";
683b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#ifdef SHOW_MODEL_BUILD
693b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[]      = "com.android.model";
707c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[]      = "com.android.build";
713b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif
727c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = {
759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = {
809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePrefixSei,
849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSuffixSei,
859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
867c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang/* uncomment to include model and build in meta */
877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1
887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
91b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    Track(MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId);
928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
9637187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t stop();
9737187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
9825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1003b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
101d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
1031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
1041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
1059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool isHevc() const { return mIsHevc; }
1061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
1071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
108c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
10970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
110dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
1118b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    static const char *getFourCCForMime(const char *mime);
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
114000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
115000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
1168c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
117000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
118000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    template<class TYPE>
121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity)
123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mEntryCapacity(entryCapacity),
125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mElementCapacity, 0);
129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_GT(mEntryCapacity, 0);
1302177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            // Ensure no integer overflow on allocation in add().
1312177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            CHECK_LT(mEntryCapacity, UINT32_MAX / mElementCapacity);
132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
14825f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity);
149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value;
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
16725f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong            if (pos >= mTotalNumTableEntries * mEntryCapacity) {
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity));
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(iterations, 0);
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            value = (*it)[(pos % (mElementCapacity * mEntryCapacity))];
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nValues  = mNumValuesInCurrEntry % mEntryCapacity;
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity];
192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t pos = nEntries * mEntryCapacity + nValues;
197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) {
201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0);
212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK_GT(nEntries, 0);
217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity);
219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries);
222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mEntryCapacity;    // # of values in each entry
233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mNumValuesInCurrEntry;  // up to mEntryCapacity
235c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
245b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    sp<IMediaSource> mSource;
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
247a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
248a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
249eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool mIsHevc;
2521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
2531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
254bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
255c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
25643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
257e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
258d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2608f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
264be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
26513aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
2661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
267c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
268c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStszTableEntries;
269be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
270c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStcoTableEntries;
271c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<off64_t> *mCo64TableEntries;
272c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStscTableEntries;
273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mStssTableEntries;
274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mSttsTableEntries;
275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    ListTableEntries<uint32_t> *mCttsTableEntries;
276965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
277000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
278000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMaxCttsOffsetTimeUs;
279965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
2813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
2823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
2833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
2843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
2853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
2863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
2873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
2883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
2893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
2903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
2913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
2923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
2933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
296548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
29793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
3003c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
30170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
30270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
30393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
30493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
30525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
306872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
307872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
308872a481558350634a3fd5cb67939de288af00ecbJames Dong
309000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
310000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
31237187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
3153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
3163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
3189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
319b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
322215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
3239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
3249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
3259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t parseHEVCCodecSpecificData(
3269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            const uint8_t *data, size_t size, HevcParameterSets &paramSets);
3279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
328215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
329faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
33093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
33103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
33219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
33319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
334c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
335c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
336c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
337c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
338c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
339c059860c73678a202bfa33062723e8f82fb779d9James Dong
340690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
341690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
34213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t mRotation;
343690f546b0ee548dbfe997df36418e5302ec2d786James Dong
3441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
3451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
3461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
34779761ab096f57c3027fad9556c2bc436672d614eJames Dong
34879761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
34979761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
350965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
35145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
35245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
35343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
3541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
360b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
361965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
363b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
3659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    void writeHvccBox();
366b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
367b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
370efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
372b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
374efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
37558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    void writeColrBox();
376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
38420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38630ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd)
387674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(dup(fd)),
388674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mInitCheck(mFd < 0? NO_INIT: OK),
389de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui      mIsRealTimeRecording(true),
390b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong      mUse4ByteNalLength(true),
3911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong      mUse32BitOffset(true),
392a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong      mIsFileSizeLimitExplicitlyRequested(false),
393a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
394a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mStarted(false),
395411ba422e3635d534928ffd81abf54f4f291c739James Dong      mWriterThreadStarted(false),
39630ab66297501757d745b9ae10da61adcd891f497Andreas Huber      mOffset(0),
39713aec890216948b0c364f8f92792129d0335f506James Dong      mMdatOffset(0),
398e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBuffer(NULL),
399e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mMoovBoxBufferOffset(0),
400e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mWriteMoovBoxToMemory(false),
401e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mFreeBoxOffset(0),
402e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStreamableFile(false),
4037837c17063a4c50bc856ba59418516fdab731de7James Dong      mEstimatedMoovBoxSize(0),
4047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang      mMoovExtraSize(0),
40507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mInterleaveDurationUs(1000000),
406e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mTimeScale(-1),
407e502b443ce9d229d1e9108834887c6e520948816Chong Zhang      mStartTimestampUs(-1ll),
40807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLatitudex10000(0),
40907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong      mLongitudex10000(0),
41086b7f47aa7482424cf8fd248f1315311919be3b0James Dong      mAreGeoTagsAvailable(false),
411ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mStartTimeOffsetMs(-1),
412ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar      mMetaKeys(new AMessage()) {
4137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    addDeviceMeta();
4142aa74dc097fe860abc84769abf2b6e0962718471Robert Shih
4152aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    // Verify mFd is seekable
4162aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    off64_t off = lseek64(mFd, 0, SEEK_SET);
4172aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    if (off < 0) {
4182aa74dc097fe860abc84769abf2b6e0962718471Robert Shih        ALOGE("cannot seek mFd: %s (%d)", strerror(errno), errno);
4192aa74dc097fe860abc84769abf2b6e0962718471Robert Shih        release();
4202aa74dc097fe860abc84769abf2b6e0962718471Robert Shih    }
42130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
42230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
4248bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4261f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
4271f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
4291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
4301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
435dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
436dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
437dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
438dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
439dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
440dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
441dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
442dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
443dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
444dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
445dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
446dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
447dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
448dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
449dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
450dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
451dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
452dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
45384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
454dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
455dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
456dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
457dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
458dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
459dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
460dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
461dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
462c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
46313210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
464377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
46513210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
466dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
467dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
468dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
469dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
4708b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static
4718b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
4728b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (mime == NULL) {
4738b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        return NULL;
4748b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
4758b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (!strncasecmp(mime, "audio/", 6)) {
4768b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
4778b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "samr";
4788b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
4798b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "sawb";
4808b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
4818b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4a";
4828b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
4838b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else if (!strncasecmp(mime, "video/", 6)) {
4848b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
4858b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4v";
4868b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
4878b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "s263";
4888b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
4898b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "avc1";
4909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
4919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return "hvc1";
4928b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
4938b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else {
4948b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        ALOGE("Track (%s) other than video or audio is not supported", mime);
4958b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
4968b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    return NULL;
4978b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan}
4988b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan
499b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissenstatus_t MPEG4Writer::addSource(const sp<IMediaSource> &source) {
500bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
501bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
50229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
503bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
504bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
505acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
506acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At most 2 tracks can be supported.
507acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.size() >= 2) {
508a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("Too many tracks (%zu) to add", mTracks.size());
509acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
510acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
511acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
512acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
513acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
514acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
515acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
516acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    bool isAudio = !strncasecmp(mime, "audio/", 6);
5178b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (Track::getFourCCForMime(mime) == NULL) {
5188b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        ALOGE("Unsupported mime '%s'", mime);
519acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return ERROR_UNSUPPORTED;
520acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
521acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
522acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // At this point, we know the track to be added is either
523acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // video or audio. Thus, we only need to check whether it
524acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // is an audio track or not (if it is not, then it must be
525acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // a video track).
526acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
527acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // No more than one video or one audio track is supported.
528acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    for (List<Track*>::iterator it = mTracks.begin();
529acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong         it != mTracks.end(); ++it) {
530acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        if ((*it)->isAudio() == isAudio) {
531acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            ALOGE("%s track already exists", isAudio? "Audio": "Video");
532acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong            return ERROR_UNSUPPORTED;
533acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        }
534acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
535acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
536acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // This is the first track of either audio or video.
537acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
538219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
5402dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
5412dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
545acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
546acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
547acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
548acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
549acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
550a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
551a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
55293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
553a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
554a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
555a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
556a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
557a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
558a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
559a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
560a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
561a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
562a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
563a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
564a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
565a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
5667c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
5677c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
5687c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
5697c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
5707c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
5717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
5727c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
5737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
5747c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
5757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
5767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
5787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
5797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD
5817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.product.model", val, NULL)
5827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5837c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Model, val, n + 1);
5847c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
5857c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5867c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
5877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
5887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
5897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
5907c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
5917c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
5927c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
5937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
5942dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
5952dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
5962dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
5972dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
5982dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
5992dec2b5be2056c6d9428897dc672185872d30d17James Dong
60078a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
6012dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
60278a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
6032dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
6042dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
6052dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
6062dec2b5be2056c6d9428897dc672185872d30d17James Dong
6072dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
6082dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
6092dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
61078a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
6112dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
6122dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
6132dec2b5be2056c6d9428897dc672185872d30d17James Dong
61478a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
615a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
61678a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
61778a1a286f736888ae7af8860b2c424af0d978848James Dong    }
61878a1a286f736888ae7af8860b2c424af0d978848James Dong
61978a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
62078a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
62178a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
62278a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
62378a1a286f736888ae7af8860b2c424af0d978848James Dong                ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
62478a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
62578a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
62678a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
62778a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
62878a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
62978a1a286f736888ae7af8860b2c424af0d978848James Dong                }
63078a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
63178a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
63278a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
63378a1a286f736888ae7af8860b2c424af0d978848James Dong            }
6342dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
6352dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
63678a1a286f736888ae7af8860b2c424af0d978848James Dong
6372dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
6382dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
6392dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6402dec2b5be2056c6d9428897dc672185872d30d17James Dong
6412dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
6422dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
6432dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
6442dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
6452dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6462dec2b5be2056c6d9428897dc672185872d30d17James Dong
6477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
6487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
6497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
650a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
651a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
6522dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
6532dec2b5be2056c6d9428897dc672185872d30d17James Dong    return factor * size;
6542dec2b5be2056c6d9428897dc672185872d30d17James Dong}
6552dec2b5be2056c6d9428897dc672185872d30d17James Dong
6562dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
657674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
65825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
65920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
661a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
662a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
663a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
664a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
665a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
666a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
667a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
668a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
669a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
670a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
6712dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
6722dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
6732dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
6742dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
6752dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
6762dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
6772dec2b5be2056c6d9428897dc672185872d30d17James Dong
6781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
6791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
6801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
6811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
6821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
6831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
6841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
6851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
6861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
687a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
688a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
689d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
690d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
6911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
6921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
6931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
694b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
695b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
696b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
697b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
698b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
6992dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7002dec2b5be2056c6d9428897dc672185872d30d17James Dong
701de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
702de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
703de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
704de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
705de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
706065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
70793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
708a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
709a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
710a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
71193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
712a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
713a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
714a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
715a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
7168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
7178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
7188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
7198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
72043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
7213856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
7228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
72377e8ae9967a078770416619e99ddb5b010def312James Dong    /*
72477e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
72577e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
7267b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
7277b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
72877e8ae9967a078770416619e99ddb5b010def312James Dong     */
72977e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
73077e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
73177e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
73277e8ae9967a078770416619e99ddb5b010def312James Dong
7337b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
7347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory is true if the amount of data in moov box is
7357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * smaller than the reserved free space at the beginning of a file, AND
7367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * when the content of moov box is constructed. Note that video/audio
7377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * frame data is always written to the file but not in the memory.
7387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Before stop()/reset() is called, mWriteMoovBoxToMemory is always
7407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
7417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * Moov box needs to be constructed.
7427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory
7447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to set to mStreamableFile so that if
7457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the file is intended to be streamable, it is set to true;
7467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * otherwise, it is set to false. When the value is set to false,
7477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * all the content of the moov box is written immediately to
7487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
7497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * content of the moov box is written to an in-memory cache,
7507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mMoovBoxBuffer, util the following condition happens. Note
7517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
7527b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
7537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 2) While the data of the moov box is written to an in-memory
7557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
7567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * If the data size surpasses the reserved space, subsequent moov
7577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * data could no longer be hold in the in-memory cache. This also
7587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
7597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * _all_ moov data must be written to the end of the file.
7607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * mWriteMoovBoxToMemory must be set to false to direct the write
7617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
7627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
7637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * 3) If the data size in moov box is smaller than the reserved
7647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space after moov box is completely constructed, the in-memory
7657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache copy of the moov box is written to the reserved free
7667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * space. Thus, immediately after the moov is completedly
7677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * constructed, mWriteMoovBoxToMemory is always set to false.
7687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
7697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = false;
7707837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBuffer = NULL;
7717837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
7727837c17063a4c50bc856ba59418516fdab731de7James Dong
773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7757837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7777837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mEstimatedMoovBoxSize == 0) {
7782dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
7792dec2b5be2056c6d9428897dc672185872d30d17James Dong        if (param) {
7802dec2b5be2056c6d9428897dc672185872d30d17James Dong            param->findInt32(kKeyBitRate, &bitRate);
7812dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
7822dec2b5be2056c6d9428897dc672185872d30d17James Dong        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
7837837c17063a4c50bc856ba59418516fdab731de7James Dong    }
78443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mEstimatedMoovBoxSize, 8);
78577e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
78677e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
78777e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
78877e8ae9967a078770416619e99ddb5b010def312James Dong        writeInt32(mEstimatedMoovBoxSize);
78977e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
79077e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
79177e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
79277e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
79377e8ae9967a078770416619e99ddb5b010def312James Dong    }
7947837c17063a4c50bc856ba59418516fdab731de7James Dong
7957837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
796c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
7971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
7981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
7991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
8001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
8011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
8021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
8041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
8051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
8061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
809a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
810a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
8121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
813a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
81425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
8181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
8191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
8201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
82137187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
822674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
82337187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
824a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
825a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
82637187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
827a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
828a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
82937187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->pause();
83037187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (status != OK) {
83137187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
83237187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
833a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
83437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
835a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
836a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
8371c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
838b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
839411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
840411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
841411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
8421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
8441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
8451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
8471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
8481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
8491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
8501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
8511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
852411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
853b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
8541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
8551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
85613f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
85713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
85813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
85913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
86013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
86113f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
86213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
86313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
86413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
86513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
86613f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
86713f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
8683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
86913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
87013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
87113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
87213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
87313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
87413f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
87513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
87613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
87713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
87813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
87913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
88013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
88113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
88213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
88313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
88413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
88513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
88613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
88713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
88813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
88913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
89013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
89113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
89213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
89313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
89413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
89513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
89613f6284305e4b27395a23db7882d670bdb1bcae1James Dong
89713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
89813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
89913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
90013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
90113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
90213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
90313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
90413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
90513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
90613f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
90713f6284305e4b27395a23db7882d670bdb1bcae1James Dong
908411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
909411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
910411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
911411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
912411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
9134c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    free(mMoovBoxBuffer);
9144c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary    mMoovBoxBuffer = NULL;
915411ba422e3635d534928ffd81abf54f4f291c739James Dong}
91613f6284305e4b27395a23db7882d670bdb1bcae1James Dong
9178bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() {
918674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
91937187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
920411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
921411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
922411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
923411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
924411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
925411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
926411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
927411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
928411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
92920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
9328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
93365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
93520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber         it != mTracks.end(); ++it) {
93637187916a486504acaf83bea30147eb5fbf46ae5James Dong        status_t status = (*it)->stop();
93737187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
93837187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
93937187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9418f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
9428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
9438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
94420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
94565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
94665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
94765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
94865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
94965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
95065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    if (mTracks.size() > 1) {
951a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
95265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
9567837c17063a4c50bc856ba59418516fdab731de7James Dong
95737187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
95837187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
959411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
96037187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
96137187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
96237187916a486504acaf83bea30147eb5fbf46ae5James Dong
96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
9641acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
965c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
9661f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
967c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
9681acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
969c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
9701f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
9711acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
972c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
9731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
974c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Construct moov box now
9777837c17063a4c50bc856ba59418516fdab731de7James Dong    mMoovBoxBufferOffset = 0;
9787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    mWriteMoovBoxToMemory = mStreamableFile;
9797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
9807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
9817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // for moov box if the file is not streamable.
9827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
9837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
9847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        CHECK(mMoovBoxBuffer != NULL);
9857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMoovBox(maxDurationUs);
98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // mWriteMoovBoxToMemory could be set to false in
9897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // MPEG4Writer::write() method
9907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mWriteMoovBoxToMemory) {
9917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        mWriteMoovBoxToMemory = false;
9927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // Content of the moov box is saved in the cache, and the in-memory
9937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // moov box needs to be written to the file in a single shot.
9947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
99543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
9967837c17063a4c50bc856ba59418516fdab731de7James Dong
9977837c17063a4c50bc856ba59418516fdab731de7James Dong        // Moov box
998c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
9997837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset = mFreeBoxOffset;
1000674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
10017837c17063a4c50bc856ba59418516fdab731de7James Dong
10027837c17063a4c50bc856ba59418516fdab731de7James Dong        // Free box
1003c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
10047837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
10057837c17063a4c50bc856ba59418516fdab731de7James Dong        write("free", 4);
10067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    } else {
10077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        ALOGI("The mp4 file will not be streamable.");
10087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
10097837c17063a4c50bc856ba59418516fdab731de7James Dong
10107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    // Free in-memory cache for moov box
10117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    if (mMoovBoxBuffer != NULL) {
10127837c17063a4c50bc856ba59418516fdab731de7James Dong        free(mMoovBoxBuffer);
10137837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBuffer = NULL;
10147837c17063a4c50bc856ba59418516fdab731de7James Dong        mMoovBoxBufferOffset = 0;
10157837c17063a4c50bc856ba59418516fdab731de7James Dong    }
10167837c17063a4c50bc856ba59418516fdab731de7James Dong
10170c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1019411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
102037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1023efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
1024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
1025efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
1026efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
1027efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
10282b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
10292b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
10302b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen        return 0;
10312b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    }
10322b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    uint32_t mpeg4Time = uint32_t(now) + delta;
1033efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
1034efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
1035efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
1036efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
1037efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
1038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
1039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
1040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
1041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
1042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
1043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
1045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
1046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
1047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
1048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
1051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
1058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
1059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
1062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
1063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
106407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
106507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
106607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1067e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeMetaBox();
1068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t id = 1;
1069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        it != mTracks.end(); ++it, ++id) {
1071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (*it)->writeTrackHeader(mUse32BitOffset);
1072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
10762cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (param && param->findInt32(kKeyFileType, &fileType) &&
1081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        fileType != OUTPUT_FORMAT_MPEG_4) {
1082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
10838284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
10848284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
10858284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
10878284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
10888284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1089b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("isom");
10908284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("mp42");
1091b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1092b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1094b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
109607ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
109707ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
109807ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
109907ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
110007ec01904613a0bac32caaa8444b4690998faed7James Dong
110107ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
110207ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
110307ec01904613a0bac32caaa8444b4690998faed7James Dong    char value[PROPERTY_VALUE_MAX];
110407ec01904613a0bac32caaa8444b4690998faed7James Dong    if (property_get("rw.media.record.test", value, NULL) &&
110507ec01904613a0bac32caaa8444b4690998faed7James Dong        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
110607ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
110707ec01904613a0bac32caaa8444b4690998faed7James Dong    }
110807ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
110907ec01904613a0bac32caaa8444b4690998faed7James Dong}
111007ec01904613a0bac32caaa8444b4690998faed7James Dong
111170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
111207ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
111307ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
111407ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
111507ec01904613a0bac32caaa8444b4690998faed7James Dong    }
111607ec01904613a0bac32caaa8444b4690998faed7James Dong
111770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
111870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
111970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
112070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
112170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
112270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
112370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
112470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
112570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
112613aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
112713aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
112813aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
112913aec890216948b0c364f8f92792129d0335f506James Dong}
113013aec890216948b0c364f8f92792129d0335f506James Dong
113113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
113213aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
113313aec890216948b0c364f8f92792129d0335f506James Dong}
113413aec890216948b0c364f8f92792129d0335f506James Dong
113513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
113613aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
113713aec890216948b0c364f8f92792129d0335f506James Dong}
113820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1139c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
1140c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
114120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1142c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    ::write(mFd,
1143c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          (const uint8_t *)buffer->data() + buffer->range_offset(),
1144c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong          buffer->range_length());
114520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
114620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mOffset += buffer->range_length();
114720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
114820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
114920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
115020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
115203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
115303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
115403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
115503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
115603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
115703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
115803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
115903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
116003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
116103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
116203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
116303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
116403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1165c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
1166c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
116730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
116830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
116903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1170b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1171b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1172c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1173b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1174c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1175b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1176c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1177b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1178c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1179c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1180c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1181c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1182c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1183b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1184b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1185b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
118643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_LT(length, 65536);
118730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1188b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1189c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1190b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1191c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1192c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1193b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1194b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
119530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
119630ab66297501757d745b9ae10da61adcd891f497Andreas Huber    return old_offset;
119730ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
119830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
11997837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1200674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
12017837c17063a4c50bc856ba59418516fdab731de7James Dong
12027837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
12037837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
12047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1205c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
12061acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        if (moovBoxSize > mEstimatedMoovBoxSize) {
12077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // The reserved moov box at the beginning of the file
12087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // is not big enough. Moov box should be written to
12097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the end of the file from now on, but not to the
12107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // in-memory cache.
12117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
12127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // We write partial moov box that is in the memory to
12137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // the file first.
1214c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
12157837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
12167837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
12177837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1218674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1219674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
12207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
12217837c17063a4c50bc856ba59418516fdab731de7James Dong            mOffset += (bytes + mMoovBoxBufferOffset);
12227b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
12237b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // All subsequent moov box content will be written
12247b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            // to the end of the file.
12257837c17063a4c50bc856ba59418516fdab731de7James Dong            mWriteMoovBoxToMemory = false;
12267837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
12277837c17063a4c50bc856ba59418516fdab731de7James Dong            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
12287837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset += bytes;
12297837c17063a4c50bc856ba59418516fdab731de7James Dong        }
12307837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1231674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
12327837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
12337837c17063a4c50bc856ba59418516fdab731de7James Dong    }
12347837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
12357837c17063a4c50bc856ba59418516fdab731de7James Dong}
12367837c17063a4c50bc856ba59418516fdab731de7James Dong
1237e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1238e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    mBoxes.push_back(mWriteMoovBoxToMemory?
1239e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            mMoovBoxBufferOffset: mOffset);
1240e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1241e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1242e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1243e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1244e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
12460c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(fourcc), 4);
124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12487837c17063a4c50bc856ba59418516fdab731de7James Dong    mBoxes.push_back(mWriteMoovBoxToMemory?
12497837c17063a4c50bc856ba59418516fdab731de7James Dong            mMoovBoxBufferOffset: mOffset);
125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
12560c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1258c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
125920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12617837c17063a4c50bc856ba59418516fdab731de7James Dong    if (mWriteMoovBoxToMemory) {
12627837c17063a4c50bc856ba59418516fdab731de7James Dong       int32_t x = htonl(mMoovBoxBufferOffset - offset);
12637837c17063a4c50bc856ba59418516fdab731de7James Dong       memcpy(mMoovBoxBuffer + offset, &x, 4);
12647837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1265c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
12667837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
12677837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1268c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
12697837c17063a4c50bc856ba59418516fdab731de7James Dong    }
127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
127120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
127220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1273674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
127520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1278674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1283674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1288674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1293674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
12970c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK_EQ(strlen(s), 4);
1298674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
129920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
130020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
130207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
130307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
130407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
130507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
130607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
130707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
130807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
130907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
131007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
131107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
131207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
131307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
131407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
131507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
131607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
131707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
131807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
131907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
132007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
132107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
132207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
132307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
132407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
132507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
132607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
132707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
132807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
132907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
133007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
133107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
133207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
133307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
133407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
133507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
133607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
133707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
133807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
133907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
134007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
134107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
134207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
134307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
134407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
134507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
134607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
134707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
134807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
134907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
135007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
135107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
135207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
135307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
135407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
135507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
135607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
135707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
135807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
135907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
136007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
136107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
136207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
136307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
136407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
136507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
136607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
136707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
136807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
13697c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
137007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
137107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
137207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1373e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1374e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1375e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1376e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1377e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
13787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
13797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
13807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1381e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1382e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1383e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
138420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1385674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
138620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
138720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
138878a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
138978a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
139078a1a286f736888ae7af8860b2c424af0d978848James Dong}
139178a1a286f736888ae7af8860b2c424af0d978848James Dong
1392d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1393d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1394d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1395d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1396d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1397d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1398956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
1399d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1400d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1401d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1402d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
14031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
140477e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
140577e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
140677e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
140777e8ae9967a078770416619e99ddb5b010def312James Dong    }
1408acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1409acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1410acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1411acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1412d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1413d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1414d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1415d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1416d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1417d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1418d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1419d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1420d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1421d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1422d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1423d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1424d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1425d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1426d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1427d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1428d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
142925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
143025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
143125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
143225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
143325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
143425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
143525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
143625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
143725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
143825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
143925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
144025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
144125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1442f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1443a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
144443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
14453c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1446065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1447f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1448a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
14493c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
14503c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
14513c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1452f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
14533c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
14543c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
14553c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
14563c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
145758ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
145858ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
145958ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
146058ae9c530247668f8af36e30d228c716c226b3d4James Dong}
146158ae9c530247668f8af36e30d228c716c226b3d4James Dong
146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
146320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
146420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1465b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId)
146620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
146725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
146820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
146920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1470a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1471a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1472eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1473bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1474c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1475956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1476be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1477c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1478c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1479c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)),
1480c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)),
1481c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)),
1482c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
1483c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong      mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)),
148420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
148525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1486548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
148713f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
148813f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mRotation(0) {
148919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
14908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
14911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
14921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
14931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
14949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
14951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
14961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
14971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
14981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1499c059860c73678a202bfa33062723e8f82fb779d9James Dong    setTimeScale();
1500c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1501c059860c73678a202bfa33062723e8f82fb779d9James Dong
15021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
15031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1504c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1505c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            ? mStcoTableEntries->count()
1506c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                            : mCo64TableEntries->count());
1507c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1508c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
15091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
151078a1a286f736888ae7af8860b2c424af0d978848James Dong    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
151178a1a286f736888ae7af8860b2c424af0d978848James Dong    if (!mOwner->isFileStreamable()) {
151278a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
151378a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1514c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1515c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1516c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1517c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
151878a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
151978a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
152078a1a286f736888ae7af8860b2c424af0d978848James Dong    }
15211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
15241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
15251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1526c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(chunkId));
1527c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(sampleId));
1528c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStscTableEntries->add(htonl(1));
15291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1532c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
15331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
153679761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
15371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
15385a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1539377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
15405a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1541c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1542c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
15431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1545965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1546965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1547965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1548965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {
1549965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1550965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1551c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1552c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1553965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1554965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1555c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1556c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1557c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1558c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1559c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1560c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1561c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
15621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
15631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1564c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
15653856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
1566c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
1567c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
1568c059860c73678a202bfa33062723e8f82fb779d9James Dong
1569c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
1570c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
1571c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
1572c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
1573c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
1574c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
1575c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1576c059860c73678a202bfa33062723e8f82fb779d9James Dong
1577c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
1578c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
1579c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
1580c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
1581c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
1582c059860c73678a202bfa33062723e8f82fb779d9James Dong
158343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
158419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
158519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
158619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
158719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
158819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
158919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
15909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint32_t type;
15919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const void *data = NULL;
15929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t size = 0;
159319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
15949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyAVCC, &type, &data, &size);
15959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
15969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyHVCC, &type, &data, &size);
159719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
159819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
159919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
160019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
16019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (esds.getCodecSpecificInfo(&data, &size) != OK) {
16029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                data = NULL;
16039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                size = 0;
160419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
160519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
160619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
16079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
16089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mGotAllCodecSpecificData = true;
16099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
161020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
161120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
161220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
161320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
161420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1615c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
1616c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
1617c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
1618c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
1619c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
1620c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
1621c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
1622c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
1623c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
1624c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
1625c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
1626c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
1627c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
1628c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
1629c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
1630c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
163220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
163320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
163420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
163520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
163620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
163793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
16383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
163993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
164093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
164193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
164293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
164393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
164493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
1645a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
164693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
164793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
164893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
164993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
165093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
165193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
16521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
16531c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
16543856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
16551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
16561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
16571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
16581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16601c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
16613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
16621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
16631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
16641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
16661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
16671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
16691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
16701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
16711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
16721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
16741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
167543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
16761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
16771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1678fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
1679a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
16805410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi        chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
1681fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1682fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
1683fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
1684fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
1685fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
16869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
1687fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                ? addLengthPrefixedSample_l(*it)
1688fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong                                : addSample_l(*it);
1689fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1690fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (isFirstSample) {
1691fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
1692fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
16931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
16941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
16951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
16961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
1697fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
16981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1699fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
17001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1702fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
17033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
17041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
170570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
170670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
1707e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
170870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
17091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
171070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
171170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
171270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
17131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
1714377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
17151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1717fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
17183856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
17191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
17211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
17221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
17241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
17251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
17261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
17271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
17281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
17291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
17301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
17343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
1735fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
17361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
17371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
17391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
17401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1741fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
17421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
17431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
17441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
1745fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
1746fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
1747fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
174870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
174970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
175070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
175170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
175270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
175370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
175470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
1755fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
17561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1758fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1759fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
17601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17621c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
17633856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
17641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1765a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
1766fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1767fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
17681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
1769fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
1770fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
1771fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1772fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
17731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
17751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1776de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
1777de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
1778de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
1779de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
1780fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
1781de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1782de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
1783de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1784fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
1785de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
1786de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
1787de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
1788fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
17891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
1790fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
1791fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
17921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
17931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17941c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
17953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
17961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
17971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
17981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
1799e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
18001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
18011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
18021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
18031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
180470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
180570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
18061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
18071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
18081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
18101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
18111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
18121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
18131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
1814411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
18151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
18161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
18171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
18181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
181993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
1820a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
1821a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
1822a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
1823a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
1824a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
182525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
182693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
182719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
182819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
182919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
183070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
183119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
183213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
183313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
183413f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
183513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
183613f6284305e4b27395a23db7882d670bdb1bcae1James Dong
183793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
183893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
1839f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
1840de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
1841a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
1842a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
1843a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
1844a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
1845a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
1846a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
184786b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
184886b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
1849a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
185086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
185186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
185286b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
185386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
185486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
1855a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
1856a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
1857a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1858f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
1859a472613aec322e25891abf5c77bf3f7e3c244920James Dong
1860f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
186125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
186225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
186325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
186425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
186520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
186620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
186720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
186820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
186920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
187020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
1871eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
1872c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
187325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
1874956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
18751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
187643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
187720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
187825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
187920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
188025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
188125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
188220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
188320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
188437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
1885a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
188637187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
1887a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
1888a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
188937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() {
189072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track stopping", mIsAudio? "Audio": "Video");
1891eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
189229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
1893eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
1894eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
1895eaae38445a340c4857c1c5569475879a728e63b7James Dong
189620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
189737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
189820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
189920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = true;
190020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
190172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopping", mIsAudio? "Audio": "Video");
190272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSource->stop();
190372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGD("%s track source stopped", mIsAudio? "Audio": "Video");
190472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
190520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
190620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
1907377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
190837187916a486504acaf83bea30147eb5fbf46ae5James Dong
1909b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
191037187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
191120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
191220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
191325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
191425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
191525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
191625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
191720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
191820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
191920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
192020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
192137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
1922377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
192320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
192420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
19263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
19293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
19303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19353856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
19363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
19373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
19383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
193947d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar    const uint8_t *nextStartCode = findNextNalStartCode(data, length);
19403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
19413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
194229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
19433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
19473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
19483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
194929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
19503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
19513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
19533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
19543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
19553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
19563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
19573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
19583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
19593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
196007b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                // COULD DO: set profile/level to the lowest required to support all SPSs
196129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
19623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
19633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
19643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
19653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
19663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
19673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
19683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
19703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
19713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
19733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
19743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
19753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
19773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
19789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 4 + 7);
19799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
19809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
19819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
19829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
19839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("copyHEVCCodecSpecificData");
19849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
19859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
19869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 23);
19879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
19889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
19899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData(
19909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, size_t minLength) {
19919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < minLength) {
1992377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
19933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
19943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
19953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
19963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
19979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
19989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
19999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
20009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
20019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = size;
20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
20033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
20053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
20073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
20113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
20123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
20163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
20193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
20203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
20233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
20243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
202529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
20273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
20293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
20303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
20323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
20333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
203429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
20353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
20363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
20383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
20413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
204229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
20473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
20513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
20523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
20533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
20543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
20573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
20583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
20593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
206029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
20613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
2065377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
20663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
20703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
20713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
20723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
20733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
207429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
20753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2078377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
20793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
20803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20821374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
20831374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
20841374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
20851374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
20863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
20873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
20883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
20903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
209129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
20923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
20933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
20943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
20951374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
20963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
20973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2098548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
209903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
210003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2101548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
210203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
210329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
210403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
210503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
210603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2108377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
210903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
211003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
211103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
21133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
21143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
211503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
211603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
211803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
211903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
212003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
21223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
212303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
21249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
21259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
21269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
21279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
21289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
212903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
21303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
21313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
21323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
21333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
213403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2136b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2137b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2138b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2139b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2140b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
214103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
21433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
21443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
21453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
21463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
21473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
21483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
21493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
21503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
21513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
21523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
21543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
21553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
21563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
21573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
21593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
21603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
21613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
21623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
21633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
21643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
21653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
21663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
21673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
21683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
21693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
21703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
21713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
21723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
217303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
217403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
217503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
217603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
21779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
21789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
21799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, HevcParameterSets &paramSets) {
21809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
21819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("parseHEVCCodecSpecificData");
21829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *tmp = data;
21839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *nextStartCode = data;
21849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t bytesLeft = size;
21859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
218647d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar        nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4);
21879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
21889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (err != OK) {
21899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
21909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
21919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
21929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Move on to find the next parameter set
21939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        bytesLeft -= nextStartCode - tmp;
21949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        tmp = nextStartCode;
21959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
21969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
21979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t csdSize = 23;
21989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const size_t numNalUnits = paramSets.getNumNalUnits();
21999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
22009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kMandatoryHevcNalUnitTypes[i];
22019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
22029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets == 0) {
22039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Cound not find NAL unit of type %d", type);
22049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
22089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kHevcNalUnitTypes[i];
22099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
22109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets > 0xffff) {
22119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
22129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
22139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        csdSize += 3;
22159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (size_t j = 0; j < numNalUnits; ++j) {
22169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (paramSets.getType(j) != type) {
22179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                continue;
22189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
22199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            csdSize += 2 + paramSets.getSize(j);
22209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
22219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = csdSize;
22239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
22249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
22259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
22279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
22289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData != NULL) {
22309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Already have codec specific data");
22319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
22329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < 4) {
22359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Codec specific data length too short: %zu", size);
22369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
22379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Data is in the form of HEVCCodecSpecificData
22409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (memcmp("\x00\x00\x00\x01", data, 4)) {
22419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return copyHEVCCodecSpecificData(data, size);
22429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    HevcParameterSets paramSets;
22459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
22463d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed parsing codec specific data");
22479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
22489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificData = malloc(mCodecSpecificDataSize);
22519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
22529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
22539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
22549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
22559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
22573d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim            &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2);
22589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (err != OK) {
22593d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed constructing HVCC atom");
22609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return err;
22619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
22629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
22639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
22649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
22659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
2266872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2267872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2268872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2269872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2270872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2271872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2272872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2273872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2274872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2275872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2276872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2277872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2278872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2279872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2280872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2281872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2282872a481558350634a3fd5cb67939de288af00ecbJames Dong
228337187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
228430ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
228513aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
228643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
228713aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
228813aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
22897c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar    int32_t nActualFrames = 0;        // frames containing non-CSD data (non-0 length)
229013aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2291965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2292965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2293965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2294965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2295965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2296000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2297a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2298965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2299000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2300000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2301000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
230243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2303c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2304e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2305a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2306a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
2307a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    } else {
2308a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
2309a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2310de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2311de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2312de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2313de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2314985f838934510983d8a887461e98dca60a6e858fJames Dong
2315d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
231620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
231793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
231820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *buffer;
231911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    const char *trackName = mIsAudio ? "Audio" : "Video";
232093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
232120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
232220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
232320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
232413aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
232520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
232620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
232720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2328a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2329a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2330a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2331a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2332a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2333a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2334a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2335a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2336a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
233730ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
233830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
233903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
234003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
234103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
23427c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // if config format (at track addition) already had CSD, keep that
23437c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // UNLESS we have not received any frames yet.
23447c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // TODO: for now the entire CSD has to come in one frame for encoders, even though
23457c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // they need to be spread out for decoders.
23467c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            if (mGotAllCodecSpecificData && nActualFrames > 0) {
23477c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                ALOGI("ignoring additional CSD for video track after first frame");
23487c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            } else {
23497c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                mMeta = mSource->getFormat(); // get output format after format change
23507c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
23517c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                if (mIsAvc) {
23527c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    status_t err = makeAVCCodecSpecificData(
23537c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
23547c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
23557c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
23567c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    CHECK_EQ((status_t)OK, err);
23577c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsHevc) {
23587c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    status_t err = makeHEVCCodecSpecificData(
23597c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
23607c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
23617c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
23627c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    CHECK_EQ((status_t)OK, err);
23637c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsMPEG4) {
23647c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
23657c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
23667c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                }
236730ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
236830ab66297501757d745b9ae10da61adcd891f497Andreas Huber
236930ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
237030ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
237130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2372548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
237330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2374a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2375a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
23767c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar        ++nActualFrames;
23777c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
2378d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2379d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2380d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2381d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2382d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2383d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
2384d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data = new MetaData(*buffer->meta_data().get());
2385d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2386d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2387d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
23889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) StripStartcode(copy);
2389e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2390b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
23919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (mIsAvc || mIsHevc) {
2392b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2393b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2394b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2395b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2396b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2397b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2398050b28a593350047845a45a14cc5026221ac1620James Dong
2399d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
24001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
24011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
24021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2403d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2404316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
2405316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileSizeLimitBytes);
2406d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2407d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2408d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2409d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2410316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
2411316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileDurationLimitUs);
2412d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2413d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2414d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2415d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2416050b28a593350047845a45a14cc5026221ac1620James Dong
2417d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2418d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2419d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2420d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2421d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
2422c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() == 0) {
242370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mFirstSampleTimeRealUs = systemTime() / 1000;
2424f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimestampUs = timestampUs;
2425f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mOwner->setStartTimestampUs(mStartTimestampUs);
24268428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs = mStartTimestampUs;
24273c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong        }
242848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2429a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mResumed) {
24308428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
243111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
243211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
243311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
243411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
243511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
24368428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
243711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
243811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
243911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
244011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
244111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
24428428af5381e835cc783b7ecb0d71cb60961c99c2James Dong            previousPausedDurationUs += pausedDurationUs - lastDurationUs;
2443a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mResumed = false;
2444a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2445a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2446a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        timestampUs -= previousPausedDurationUs;
244711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
244811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
244911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
245011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
245111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2452000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        if (!mIsAudio) {
2453965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            /*
2454965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Composition time: timestampUs
2455965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             * Decoding time: decodingTimeUs
2456000e18370baae60ffd9f25b509501dd8c26deabfJames Dong             * Composition time offset = composition time - decoding time
2457965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong             */
2458965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            int64_t decodingTimeUs;
2459965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
2460965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            decodingTimeUs -= previousPausedDurationUs;
2461000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            cttsOffsetTimeUs =
2462000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
246311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
246411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
246511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
246611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
246711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2468965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong            timestampUs = decodingTimeUs;
2469a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
2470000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                timestampUs, cttsOffsetTimeUs);
2471000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2472000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts box table if necessary
2473000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            currCttsOffsetTimeTicks =
2474000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
247511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
247611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
247711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                return ERROR_MALFORMED;
247811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
247911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2480c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
248143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // Force the first ctts table entry to have one single entry
248243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // so that we can do adjustment for the initial track start
248343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                // time offset easily in writeCttsBox().
248443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
248543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
248643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                cttsSampleCount = 0;      // No sample in ctts box is pending
248743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            } else {
248843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
248943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
249043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
249143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    cttsSampleCount = 1;  // One sample in ctts box is pending
249243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                } else {
249343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                    ++cttsSampleCount;
249443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
249543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
2496000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2497000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            // Update ctts time offset range
2498c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 0) {
2499000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2500000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2501000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            } else {
2502000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
2503000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2504000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
2505000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                    mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
2506000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
2507000e18370baae60ffd9f25b509501dd8c26deabfJames Dong            }
2508000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
2509965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        }
2510872a481558350634a3fd5cb67939de288af00ecbJames Dong
2511de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        if (mOwner->isRealTimeRecording()) {
2512872a481558350634a3fd5cb67939de288af00ecbJames Dong            if (mIsAudio) {
2513872a481558350634a3fd5cb67939de288af00ecbJames Dong                updateDriftTime(meta_data);
2514e259531ce59ab1f31de5a23124b22536f6a5a767James Dong            }
2515e259531ce59ab1f31de5a23124b22536f6a5a767James Dong        }
2516872a481558350634a3fd5cb67939de288af00ecbJames Dong
251711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
251811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
251911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            return ERROR_MALFORMED;
252011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih        }
252111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2522a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
252311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, previousPausedDurationUs);
2524c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong        if (timestampUs > mTrackDurationUs) {
2525c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong            mTrackDurationUs = timestampUs;
25263b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber        }
25273b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber
25285a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // We need to use the time scale based ticks, rather than the
25295a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // timestamp itself to determine whether we have to use a new
25305a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // stts entry, since we may have rounding errors.
25315a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // The calculation is intended to reduce the accumulated
25325a217fba010e801c255503602bda4b86ac5a6ac9James Dong        // rounding errors.
25335a217fba010e801c255503602bda4b86ac5a6ac9James Dong        currDurationTicks =
25345a217fba010e801c255503602bda4b86ac5a6ac9James Dong            ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
25355a217fba010e801c255503602bda4b86ac5a6ac9James Dong                (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
2536c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (currDurationTicks < 0ll) {
2537f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang            ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
2538f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang                    (long long)timestampUs, (long long)lastTimestampUs, trackName);
253911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            copy->release();
25400332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang            mSource->stop();
2541c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return UNKNOWN_ERROR;
25428c460498c028888c533ab442be12b6d4b669b965James Dong        }
25438c460498c028888c533ab442be12b6d4b669b965James Dong
254485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // if the duration is different for this sample, see if it is close enough to the previous
254585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // duration that we can fudge it and use the same value, to avoid filling the stts table
254685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // with lots of near-identical entries.
254785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // "close enough" here means that the current duration needs to be adjusted by less
254885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        // than 0.1 milliseconds
254985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
255085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
255185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                    + (mTimeScale / 2)) / mTimeScale;
255285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            if (deltaUs > -100 && deltaUs < 100) {
255385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // use previous ticks, and adjust timestamp as if it was actually that number
255485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                // of ticks
255585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                currDurationTicks = lastDurationTicks;
255685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen                timestampUs += deltaUs;
255785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
255885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen        }
255985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen
2560c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStszTableEntries->add(htonl(sampleSize));
2561c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        if (mStszTableEntries->count() > 2) {
2562c059860c73678a202bfa33062723e8f82fb779d9James Dong
2563a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // Force the first sample to have its own stts entry so that
2564a472613aec322e25891abf5c77bf3f7e3c244920James Dong            // we can adjust its value later to maintain the A/V sync.
2565c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
256679761ab096f57c3027fad9556c2bc436672d614eJames Dong                addOneSttsTableEntry(sampleCount, lastDurationTicks);
2567be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                sampleCount = 1;
2568be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            } else {
2569be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                ++sampleCount;
2570be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
2571965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
2572be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2573be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        if (mSamplesHaveSameSize) {
2574c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
2575be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong                mSamplesHaveSameSize = false;
2576be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
25778644c14618d30d9e57a69df40ed939986ebf02c4James Dong            previousSampleSize = sampleSize;
2578be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        }
2579a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
258011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                trackName, timestampUs, lastTimestampUs);
25818644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastDurationUs = timestampUs - lastTimestampUs;
2582c059860c73678a202bfa33062723e8f82fb779d9James Dong        lastDurationTicks = currDurationTicks;
25838644c14618d30d9e57a69df40ed939986ebf02c4James Dong        lastTimestampUs = timestampUs;
258420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2585d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        if (isSync != 0) {
2586c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            addOneStssTableEntry(mStszTableEntries->count());
2587d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        }
2588d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
258993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (mTrackingProgressStatus) {
259093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            if (mPreviousTrackTimeUs <= 0) {
259193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong                mPreviousTrackTimeUs = mStartTimestampUs;
259293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
2593faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong            trackProgressStatus(timestampUs);
259493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
259543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
25969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addLengthPrefixedSample_l(copy)
259758ae9c530247668f8af36e30d228c716c226b3d4James Dong                                 : mOwner->addSample_l(copy);
2598c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2599c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t count = (mOwner->use32BitFileOffset()
2600c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        ? mStcoTableEntries->count()
2601c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        : mCo64TableEntries->count());
2602c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2603c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (count == 0) {
26041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong                addChunkOffset(offset);
260558ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
260658ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
260758ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
260858ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
260958ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
261013aec890216948b0c364f8f92792129d0335f506James Dong
261113aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
261213aec890216948b0c364f8f92792129d0335f506James Dong        if (interleaveDurationUs == 0) {
26131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
26141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
261513aec890216948b0c364f8f92792129d0335f506James Dong        } else {
261613aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
261713aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
261813aec890216948b0c364f8f92792129d0335f506James Dong            } else {
261943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
262043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
262143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
262243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
262343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
262413aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
262513aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
2626c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
2627c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
2628c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
262913aec890216948b0c364f8f92792129d0335f506James Dong                    }
26301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
263113aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
263213aec890216948b0c364f8f92792129d0335f506James Dong                }
263313aec890216948b0c364f8f92792129d0335f506James Dong            }
263413aec890216948b0c364f8f92792129d0335f506James Dong        }
263513aec890216948b0c364f8f92792129d0335f506James Dong
263620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
263725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
263845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
2639690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
2640f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
264145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2642bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
2643be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
264413aec890216948b0c364f8f92792129d0335f506James Dong    // Last chunk
264543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (!hasMultipleTracks) {
2646c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        addOneStscTableEntry(1, mStszTableEntries->count());
264758ae9c530247668f8af36e30d228c716c226b3d4James Dong    } else if (!mChunkSamples.empty()) {
26481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        addOneStscTableEntry(++nChunks, mChunkSamples.size());
26491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        bufferChunk(timestampUs);
265013aec890216948b0c364f8f92792129d0335f506James Dong    }
265113aec890216948b0c364f8f92792129d0335f506James Dong
2652be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // We don't really know how long the last frame lasts, since
2653be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // there is no frame time after it, just repeat the previous
2654be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    // frame's duration.
2655c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 1) {
26568f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        lastDurationUs = 0;  // A single sample's duration
265779761ab096f57c3027fad9556c2bc436672d614eJames Dong        lastDurationTicks = 0;
2658be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
2659be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong        ++sampleCount;  // Count for the last sample
2660be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    }
2661a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2662c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() <= 2) {
266379761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(1, lastDurationTicks);
2664a472613aec322e25891abf5c77bf3f7e3c244920James Dong        if (sampleCount - 1 > 0) {
266579761ab096f57c3027fad9556c2bc436672d614eJames Dong            addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
2666a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
2667a472613aec322e25891abf5c77bf3f7e3c244920James Dong    } else {
266879761ab096f57c3027fad9556c2bc436672d614eJames Dong        addOneSttsTableEntry(sampleCount, lastDurationTicks);
2669a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2670a472613aec322e25891abf5c77bf3f7e3c244920James Dong
267143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // The last ctts box may not have been written yet, and this
267243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    // is to make sure that we write out the last ctts box.
267343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
267443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        if (cttsSampleCount > 0) {
267543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
267643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
267743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    }
267843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
2679c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs += lastDurationUs;
268025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
268143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
268243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
268343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2684df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
268511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
2686872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
2687a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
2688872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2689365a963142093a1cd8efdcea76b5f65096a5b115James Dong
269037187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
269137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
269237187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
269337187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
2694365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
2695365a963142093a1cd8efdcea76b5f65096a5b115James Dong
269645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
2697c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mStszTableEntries->count() == 0) {                      // no samples written
269829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
269945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
270045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
270145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
2702c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (!mIsAudio && mStssTableEntries->count() == 0) {  // no sync frames for video
270329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
270445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
270545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
270645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
270745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
270845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
270945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
271045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
271145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
271245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
271345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
271443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
271507ec01904613a0bac32caaa8444b4690998faed7James Dong
271607ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
271707ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
271807ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
271907ec01904613a0bac32caaa8444b4690998faed7James Dong    }
272007ec01904613a0bac32caaa8444b4690998faed7James Dong
272143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
272243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
272343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
272443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
272543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mIsAudio? 0: 1);
272643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
272743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
272843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
272943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
273043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
273143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
273243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
2733c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
273443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
273586b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
273686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
273786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
273886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
273986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
274086b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
274186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
274286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
274386b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
274486b7f47aa7482424cf8fd248f1315311919be3b0James Dong
274586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
274670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
274770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
274886b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
274970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
275007ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
275107ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
275207ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
275307ec01904613a0bac32caaa8444b4690998faed7James Dong
275443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
275543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
275643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
275743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
275870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
275970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
276070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
276170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
276270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
276370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
276470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
276570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
276643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
276743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
276843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
2769faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
2770a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
2771c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2772215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
2773215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
2774a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
2775bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
277693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
277793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
277893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
277993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2780faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
2781bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
2782faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
2783bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
2784faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2785faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
2786faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
2787faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
2788bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
2789bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
2790faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2791faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
2792faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2793faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2794faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
2795faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
2796bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2797bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
2798faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
2799faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
2800faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
2801bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
2802bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
2803faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
2804faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
2805faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
2806faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
2807d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
2808a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
2809e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2810d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
2811e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2812e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2813e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
2814a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
2815e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
2816e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
2817e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
2818e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2819de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
2820de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
2821de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
2822de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2823b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
2824b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
2825b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
2826b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
28271c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
28283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
28291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
28301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
28311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
283213aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
283320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
283420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28353b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
2836c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    return mTrackDurationUs;
283720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
283820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2839d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
2840d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
2841d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
2842d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2843690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
2844690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
2845690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
2846690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
2847690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
28489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
28499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
2850690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
2851690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
285229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
2853690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2854690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2855690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
2856690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
2857690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
285829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
2859690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
2860690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
2861690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
2862690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
2863690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
2864690f546b0ee548dbfe997df36418e5302ec2d786James Dong
2865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
286620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28673856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("%s track time scale: %d",
28681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsAudio? "Audio": "Video", mTimeScale);
28698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
2870efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
2871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
2872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
2873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
2874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
2875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
2876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
2877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
2878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
2879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                } else {
2880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
2881b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
2882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
2883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
2884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
2885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
2886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
2887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
2892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
2895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
2901965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    writeCttsBox();
2902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!mIsAudio) {
2903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
2904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
2907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
2909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
2912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
29158b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
29168b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
291729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
29218b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    mOwner->beginBox(fourcc);        // video format
2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
2925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
2926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
2930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
2932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
2933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
2934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
2935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
2937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
2938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
2939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
2940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
2942c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
2943c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
2946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
294743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(23 + mCodecSpecificDataSize, 128);
2948b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
29559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
29569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        writeHvccBox();
2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
296058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    writeColrBox();
2961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
2962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
2963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
296458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() {
296558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    ColorAspects aspects;
296658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    memset(&aspects, 0, sizeof(aspects));
296758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    // TRICKY: using | instead of || because we want to execute all findInt32-s
296858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
296958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
297058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
297158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
297258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t primaries, transfer, coeffs;
297358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        bool fullRange;
297458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorUtils::convertCodecColorAspectsToIsoAspects(
297558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                aspects, &primaries, &transfer, &coeffs, &fullRange);
297658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->beginBox("colr");
297758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeFourcc("nclx");
297858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(primaries);
297958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(transfer);
298058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(coeffs);
298158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt8(fullRange ? 128 : 0);
298258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->endBox(); // colr
298358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
298458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar}
298558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
2986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
2987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
2988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
2989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
29908b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
29918b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
299229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
2993b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(!"should not be here, unknown mime type.");
2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
3006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
3010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
3011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
3013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
3014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
3015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
3016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
3017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
3018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
3023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
302543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
3026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
302843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_LT(mCodecSpecificDataSize + 23, 128);
3029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3030b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
3031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
3037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
3039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
3040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
304246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt8(0x00);   // buffer size 24-bit (0x300)
304346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
304496bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
304546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
304696bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
304746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
304846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
304946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
3050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
3052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
306743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mCodecSpecificDataSize, 0);
3068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
3071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
3073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
3075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
3076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
3078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
3080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
3081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
308346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        0x01, 0x77, 0x00, // buffer size 96000 bytes
3084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3085b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
3086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
308796bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
308846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
308996bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
309046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
309146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
309246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
309346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
3094b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
3095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3098b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3099b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3100b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3104b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3105b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3106b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3109efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
3110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
3111b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
3112b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
3113b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
3114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3115b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3116219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
3117b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
31188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
3119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
3120b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
3121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
3122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
3123b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3124b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3125b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
3126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
3127b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
3128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
3129b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3130b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
313120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3132b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
3133b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3134b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3135b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
3136b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
3137b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        bool success = mMeta->findInt32(kKeyWidth, &width);
3138b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        success = success && mMeta->findInt32(kKeyHeight, &height);
3139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
3140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
3142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
3143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
3145b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3147b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
3148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
3149b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
3150b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
3151b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
3152b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3153b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3154b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3155b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3157b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
3158b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
3159b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
3160b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
3161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3162b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3164b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3165b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
3166b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
3167b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3168b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
3169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
3170b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3171b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3172b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3173b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
3174b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
3175b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3176b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3177b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3178efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3179b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
3180b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
3181b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3182b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3183b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3184b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mTimeScale);    // media timescale
3185b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3186b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(mdhdDuration);  // use media timescale
3187b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
3188b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
3189b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
3190b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
3191b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
3192b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // language code
3193b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
3194b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3195b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3196b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3197b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
3198b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
3199b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
3200b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
3201b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
3202b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
3203b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
3204b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
3205b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3206b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3207b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3208b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
3209b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
3210b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
3211b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
3212b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3213b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
3214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3216b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
3217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
3218b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
3220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
3221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
3222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
3225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
3226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
3227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
3228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
3231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
323243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(mCodecSpecificDataSize, 5);
3233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
3235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
3236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
3239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
3241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
32439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
32449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() {
32459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK(mCodecSpecificData);
32469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK_GE(mCodecSpecificDataSize, 5);
32479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
32489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Patch avcc's lengthSize field to match the number
32499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // of bytes we use to indicate the size of a nal unit.
32509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
32519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
32529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->beginBox("hvcC");
32539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
32549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->endBox();  // hvcC
32559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
32569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
3257b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
3258b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
3259b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
3260b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
3261b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
3262b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
3263b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
3264b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3265b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3266b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
3267b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
3268b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3269b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3270b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3271b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3272b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3273b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3274000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3275a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3276b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mStartTimestampUs != moovStartTimeUs) {
327843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3279b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3281000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
3282000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3283000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3284000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3285000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3286000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3287c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3288c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mSttsTableEntries->get(duration, 1));
3289c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back to host byte order
3290c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
3291c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
3292b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
3293b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
329420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3295965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
3296965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    if (mIsAudio) {  // ctts is not for audio
3297965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3298965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3299965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3300000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
3301000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
3302000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
3303000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
3304000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3305965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
3306c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
3307965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
3308965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
3309965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3310a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
3311c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
3312965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3313965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
3314000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3315c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t duration;
3316c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    CHECK(mCttsTableEntries->get(duration, 1));
3317c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    duration = htonl(duration);  // Back host byte order
3318c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1);
3319c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
3320965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
3321965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
3322965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
3323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
3324b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
3325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3326c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
3327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
3328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
332925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
3330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
3331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
3332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3333c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
3334c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
3335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
3336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
333720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
3339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
3340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3341c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
3342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
3343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
334420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
3346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
3347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3348c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
3349c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
3350c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
3351c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
3352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
335420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
335520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
335607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
335707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
335807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
335907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
336007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
336107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
3362e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() {
3363e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
3364e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
3365e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
3366e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeFourcc("mdta");
3367e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
3368e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
3369e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
3370e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
3371e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3372e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3373e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3374e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
3375e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3376e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3377e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
3378e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
3379e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
3380e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3381e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3382e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3383e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
3384e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
3385e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
3386e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
3387e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3388e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3389e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3390e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3391e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
3392e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3393e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3394e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
3395e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
3396e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
3397e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
3398e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
3399e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
3400e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
34017c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
34027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
34037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
34047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
34057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
34067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
34077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
34087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
34097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
34107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
3411e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
3412e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3413e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
3414e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
34157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
34167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3417e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
3418e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3419e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3420e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3421e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
3422e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3423e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
3424e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
34257c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
34267c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3427e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
3428e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3429e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3430e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3431e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
3432e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
3433e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
34347c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
34357c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
3436e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
3437e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
3438e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
3439e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
3440e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
3441e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
3442e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3443e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
3444e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3445e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3446e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() {
3447e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
3448e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
3449e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
3450e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
3451e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
3452e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
3453e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeHdlr();
3454e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
3455e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
3456e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
3457e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
3458e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
345907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
346007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
346107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
346207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
346307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
346407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
346507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
346607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
346707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
3468432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
3469432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
347007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
347107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
347207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
347307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
347407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
347507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
347607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
347707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
347820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3479