MPEG4Writer.cpp revision 2504ce46a75c86bb1f8ed6f839dd30e2ec7b400a
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
20826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar#include <algorithm>
21826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
23a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <fcntl.h>
24a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h>
26a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/prctl.h>
27a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/stat.h>
28a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/types.h>
29a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <unistd.h>
30a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
31a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <utils/Log.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar#include <functional>
34c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar
35d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/MediaSource.h>
3643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong#include <media/stagefright/foundation/ADebug.h>
37e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang#include <media/stagefright/foundation/AMessage.h>
38826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar#include <media/stagefright/foundation/AUtils.h>
39607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang#include <media/stagefright/foundation/ByteUtils.h>
4058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar#include <media/stagefright/foundation/ColorUtils.h>
41d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/stagefright/foundation/avc_utils.h>
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h>
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
4518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
4603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h>
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
48d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h>
4907ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h>
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h"
529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include "include/HevcUtils.h"
53dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
54dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false
55dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
56dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif
57dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn
5811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \
59dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \
6011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    ALOGW("Condition %s failed "  message, #condition, ##__VA_ARGS__); \
6111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih    true; \
6211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih}))
6311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6677e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
671f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32
681f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // filesystem file size
691f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad                                                         // used by most SD cards
703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07;
713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08;
7270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs     = 700000LL;
73e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuangstatic const int64_t kMaxMetadataSize = 0x4000000LL;   // 64MB max per-frame metadata size
745b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong
757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[]    = "com.android.version";
76da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuangstatic const char kMetaKey_Manufacturer[]      = "com.android.manufacturer";
773b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[]      = "com.android.model";
78da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang
79da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang#ifdef SHOW_BUILD
807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[]      = "com.android.build";
813b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif
827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
834dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatic const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count";
847c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
8562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuangstatic const int kTimestampDebugCount = 10;
8662a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = {
889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = {
939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePrefixSei,
979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSuffixSei,
989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
99da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang/* uncomment to include build in meta */
1007c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1
1017c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
104ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kang    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
1058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
109fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    status_t stop(bool stopSource = true);
11037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
11125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1133b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
114d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
115fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int32_t getMetaSizeIncrease() const;
116b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
117230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t getMinCttsOffsetTimeUs();
1181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
1191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
1209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool isHevc() const { return mIsHevc; }
121fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    bool isHeic() const { return mIsHeic; }
1221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
1231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
124fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    bool usePrefix() const { return mIsAvc || mIsHevc || mIsHeic; }
125c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
126fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    void addItemOffsetAndSize(off64_t offset, size_t size);
12770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
128dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
1298b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    static const char *getFourCCForMime(const char *mime);
13025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *getTrackType() const;
131fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    void resetInternal();
13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
134000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
13505f4cd73b9655a6d4aad9fa215d6fc13c40633aaZhijun He        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
1368c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
137000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
138000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
140c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    template<class TYPE, unsigned ENTRY_SIZE>
141c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    // ENTRY_SIZE: # of values in each entry
142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
143c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        static_assert(ENTRY_SIZE > 0, "ENTRY_SIZE must be positive");
144c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        ListTableEntries(uint32_t elementCapacity)
145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
149b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_GT(mElementCapacity, 0u);
1502177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            // Ensure no integer overflow on allocation in add().
151c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(ENTRY_SIZE, UINT32_MAX / mElementCapacity);
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
168c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(pos, mTotalNumTableEntries * ENTRY_SIZE);
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
171c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
177b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_EQ(iterations, 0u);
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
179c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            (*it)[(pos % (mElementCapacity * ENTRY_SIZE))] = value;
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
187c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if (pos >= mTotalNumTableEntries * ENTRY_SIZE) {
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
192c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
198b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_EQ(iterations, 0u);
199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
200c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            value = (*it)[(pos % (mElementCapacity * ENTRY_SIZE))];
201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
204c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // adjusts all values by |adjust(value)|
205c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        void adjustEntries(
206c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                std::function<void(size_t /* ix */, TYPE(& /* entry */)[ENTRY_SIZE])> update) {
207c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t nEntries = mTotalNumTableEntries + mNumValuesInCurrEntry / ENTRY_SIZE;
208c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t ix = 0;
209c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            for (TYPE *entryArray : mTableEntryList) {
210c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                size_t num = std::min(nEntries, (size_t)mElementCapacity);
211c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                for (size_t i = 0; i < num; ++i) {
212c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    update(ix++, (TYPE(&)[ENTRY_SIZE])(*entryArray));
213c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    entryArray += ENTRY_SIZE;
214c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                }
215c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                nEntries -= num;
216c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            }
217c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        }
218c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar
219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
224c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t nValues  = mNumValuesInCurrEntry % ENTRY_SIZE;
225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
226c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                mCurrTableEntriesElement = new TYPE[ENTRY_SIZE * mElementCapacity];
227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
231c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t pos = nEntries * ENTRY_SIZE + nValues;
232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
235c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if ((mNumValuesInCurrEntry % ENTRY_SIZE) == 0) {
236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
246b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_EQ(mNumValuesInCurrEntry % ENTRY_SIZE, 0u);
247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
251b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross                CHECK_GT(nEntries, 0u);
252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
253c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, mElementCapacity);
254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
256c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, nEntries);
257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
258c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
261c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
262c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
263c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
264c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
265c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
267c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
268c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t         mNumValuesInCurrEntry;  // up to ENTRY_SIZE
269c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
270c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
271c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
272c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
276c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
279ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kang    sp<MediaSource> mSource;
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
281a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
282a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
283eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool mIsHevc;
2861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
28725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    bool mIsVideo;
288fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    bool mIsHeic;
2891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
290fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    bool mGotStartKeyFrame;
2919db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    bool mIsMalformed;
292bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
293c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
29443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
295826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    int64_t mLastDecodingTimeUs;
296e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
297d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
2981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
2998f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
303be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
30413aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
3051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
306c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
307c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStszTableEntries;
308be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
309c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStcoTableEntries;
310c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<off64_t, 1> *mCo64TableEntries;
311c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 3> *mStscTableEntries;
312c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStssTableEntries;
313c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mSttsTableEntries;
314c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mCttsTableEntries;
315965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
316000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
317230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t mMinCttsOffsetTicks;
318230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t mMaxCttsOffsetTicks;
319965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
320dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    // Save the last 10 frames' timestamp and frame type for debug.
321dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    struct TimestampDebugHelperEntry {
322dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        int64_t pts;
323dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        int64_t dts;
324dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        std::string frameType;
325dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    };
326dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang
327dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    std::list<TimestampDebugHelperEntry> mTimestampDebugHelper;
32862a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
3293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
3303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
3313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
3323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
3333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
3353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
3363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
3373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
3383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
3393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
3403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
3413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
3423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
345548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
34693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
3493c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
35070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
35170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
35293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
35393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
35425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
355fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int32_t mRotation;
356fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
357fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    Vector<uint16_t> mProperties;
358fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    Vector<uint16_t> mDimgRefs;
359fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int32_t mIsPrimary;
360fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int32_t mWidth, mHeight;
36167d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang    int32_t mTileWidth, mTileHeight;
362fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int32_t mGridRows, mGridCols;
363fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    size_t mNumTiles, mTileIndex;
364fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
365872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
366872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
367872a481558350634a3fd5cb67939de288af00ecbJames Dong
36862a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    void dumpTimeStamps();
36962a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
370230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t getStartTimeOffsetTimeUs() const;
371000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
372000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
37437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
3773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
3783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
3809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
384215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
3859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
3869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
3879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t parseHEVCCodecSpecificData(
3889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            const uint8_t *data, size_t size, HevcParameterSets &paramSets);
3899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
390215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
391faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
39293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
39303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
39419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
39519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
396c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
397c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
398c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
399c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
400c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
401c059860c73678a202bfa33062723e8f82fb779d9James Dong
402690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
403690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
404690f546b0ee548dbfe997df36418e5302ec2d786James Dong
4051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
4061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
4071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
40879761ab096f57c3027fad9556c2bc436672d614eJames Dong
40979761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
41079761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
411965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
41245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
41345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
41443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
4151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
422965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
4269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    void writeHvccBox();
427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
429b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
430b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
431efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
433b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
43425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    void writeNmhdBox();
435b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
436efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
43758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    void writeColrBox();
438b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
439b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
441b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
44225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    void writeMetadataFourCCBox();
443b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
444b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
449fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu KuangMPEG4Writer::MPEG4Writer(int fd) {
4505ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    initInternal(fd, true /*isFirstSession*/);
45130ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
45230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
45320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
4548bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
4571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
4591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
4601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
463fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
464fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd != -1) {
465fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        close(mNextFd);
466fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
467fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
468fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
4695ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuangvoid MPEG4Writer::initInternal(int fd, bool isFirstSession) {
470fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("initInternal");
4718fdb3fde346b446ad3b04dafa65a6844da672e23Hangyu Kuang    mFd = dup(fd);
472fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mNextFd = -1;
473fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mInitCheck = mFd < 0? NO_INIT: OK;
4745ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
4755ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mInterleaveDurationUs = 1000000;
4765ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
4775ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mStartTimestampUs = -1ll;
4785ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mStartTimeOffsetMs = -1;
479fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mPaused = false;
480fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStarted = false;
481fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mWriterThreadStarted = false;
482fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSendNotify = false;
4835ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
4845ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    // Reset following variables for all the sessions and they will be
4855ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    // initialized in start(MetaData *param).
4865ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mIsRealTimeRecording = true;
4875ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mUse4ByteNalLength = true;
4885ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mUse32BitOffset = true;
489fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mOffset = 0;
490fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMdatOffset = 0;
491720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCache = NULL;
492720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCacheOffset = 0;
493720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCacheSize = 0;
494720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mWriteBoxToMemory = false;
495fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mFreeBoxOffset = 0;
496fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStreamableFile = false;
497fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mTimeScale = -1;
498fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mHasFileLevelMeta = false;
499fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mPrimaryItemId = 0;
500fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mAssociationEntryCount = 0;
501fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mNumGrids = 0;
5025ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
5035ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    // Following variables only need to be set for the first recording session.
5045ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    // And they will stay the same for all the recording sessions.
5055ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    if (isFirstSession) {
5065ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mMoovExtraSize = 0;
5072504ce46a75c86bb1f8ed6f839dd30e2ec7b400aHangyu Kuang        mHasMoovBox = false;
5085ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mMetaKeys = new AMessage();
5095ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        addDeviceMeta();
5105ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mLatitudex10000 = 0;
5115ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mLongitudex10000 = 0;
5125ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mAreGeoTagsAvailable = false;
5135ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mSwitchPending = false;
5145ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mIsFileSizeLimitExplicitlyRequested = false;
5155ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    }
5165ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
517fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // Verify mFd is seekable
518fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    off64_t off = lseek64(mFd, 0, SEEK_SET);
519fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (off < 0) {
520fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGE("cannot seek mFd: %s (%d) %lld", strerror(errno), errno, (long long)mFd);
521fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        release();
522fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
523fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
524fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         it != mTracks.end(); ++it) {
525fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        (*it)->resetInternal();
526fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
529dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
530dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
531dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
532dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
533dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
534dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
535dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
536dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
537dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
538dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
539dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
540dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
541dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
542dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
543dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
544dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
545dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
546dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
54784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
548dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
549dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
550dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
55125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    snprintf(buffer, SIZE, "     %s track\n", getTrackType());
552dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
553dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
554dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
555dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
556c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
55713210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
558377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
55913210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
560dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
561dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
562dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
563dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
5648b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static
5658b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
5668b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (mime == NULL) {
5678b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        return NULL;
5688b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5698b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (!strncasecmp(mime, "audio/", 6)) {
5708b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
5718b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "samr";
5728b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
5738b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "sawb";
5748b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
5758b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4a";
5768b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
5778b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else if (!strncasecmp(mime, "video/", 6)) {
5788b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
5798b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4v";
5808b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
5818b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "s263";
5828b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
5838b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "avc1";
5849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
5859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return "hvc1";
5868b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
58725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (!strncasecmp(mime, "application/", 12)) {
58825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        return "mett";
589fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    } else if (!strcasecmp(MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, mime)) {
590fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        return "heic";
5918b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else {
59225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Track (%s) other than video/audio/metadata is not supported", mime);
5938b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5948b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    return NULL;
5958b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan}
5968b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan
597ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kangstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
598bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
599bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
60029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
601bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
602bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
603acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
604acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
605acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
606acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
607acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
608acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
60925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (Track::getFourCCForMime(mime) == NULL) {
61025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Unsupported mime '%s'", mime);
61125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        return ERROR_UNSUPPORTED;
61225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
61325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
61425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    // This is a metadata track or the first track of either audio or video
615acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
616219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
6182dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
619fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mHasMoovBox |= !track->isHeic();
620fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mHasFileLevelMeta |= track->isHeic();
621fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
6222dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
626acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
627acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
628acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
629acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
630acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
631a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
632a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
63393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
634a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
635a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
636a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
637a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
638a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
639a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
640a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
641a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
642a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
643a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
644a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
645a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
646a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
6477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
6487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
6497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
6507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
6517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
6527c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
6537c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
6547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
6557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
6567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
6577c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6587c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
6597c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
6607c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
661da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang
662da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang    if (property_get_bool("media.recorder.show_manufacturer_and_model", false)) {
663da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        if (property_get("ro.product.manufacturer", val, NULL)
664da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang                && (n = strlen(val)) > 0) {
665da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMetaKeys->setString(kMetaKey_Manufacturer, val, n + 1);
666da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMoovExtraSize += sizeof(kMetaKey_Manufacturer) + n + 32;
667da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        }
668da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        if (property_get("ro.product.model", val, NULL)
669da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang                && (n = strlen(val)) > 0) {
670da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMetaKeys->setString(kMetaKey_Model, val, n + 1);
671da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
672da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        }
6737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
674da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang#ifdef SHOW_MODEL_BUILD
6757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
6767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
6787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
6797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
6817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
6827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
683fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangint64_t MPEG4Writer::estimateFileLevelMetaSize() {
684fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // base meta size
685fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int64_t metaSize =     12  // meta fullbox header
686fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 33  // hdlr box
687fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 14  // pitm box
688fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 16  // iloc box (fixed size portion)
689fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 14  // iinf box (fixed size portion)
690fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 32  // iprp box (fixed size protion)
691fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 8   // idat box (when empty)
692fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 12  // iref box (when empty)
693fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         ;
694fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
695fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (List<Track *>::iterator it = mTracks.begin();
696fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang         it != mTracks.end(); ++it) {
697fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if ((*it)->isHeic()) {
698fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            metaSize += (*it)->getMetaSizeIncrease();
699fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
700fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
701fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
702fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    ALOGV("estimated meta size: %lld", (long long) metaSize);
703fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
704fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // Need at least 8-byte padding at the end, otherwise the left-over
705fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // freebox may become malformed
706fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    return metaSize + 8;
707fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
708fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
7092dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
7102dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
7112dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
7122dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
7132dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
7142dec2b5be2056c6d9428897dc672185872d30d17James Dong
71578a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
7162dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
71778a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
7182dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
7192dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
7202dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
7212dec2b5be2056c6d9428897dc672185872d30d17James Dong
7222dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
7232dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
7242dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
72578a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
7262dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
7272dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
7282dec2b5be2056c6d9428897dc672185872d30d17James Dong
72978a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
730a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
73178a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
73278a1a286f736888ae7af8860b2c424af0d978848James Dong    }
73378a1a286f736888ae7af8860b2c424af0d978848James Dong
73478a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
73578a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
73678a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
73778a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
7380ca31521644b9396829850f7400d23f9b107cc64Johan Redestig                ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000;
73978a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
74078a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
74178a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
74278a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
74378a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
74478a1a286f736888ae7af8860b2c424af0d978848James Dong                }
74578a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
74678a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
74778a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
74878a1a286f736888ae7af8860b2c424af0d978848James Dong            }
7492dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
7502dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
75178a1a286f736888ae7af8860b2c424af0d978848James Dong
7522dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
7532dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
7542dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7552dec2b5be2056c6d9428897dc672185872d30d17James Dong
7562dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
7572dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
7582dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
7592dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
7602dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7612dec2b5be2056c6d9428897dc672185872d30d17James Dong
7627c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
7637c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
7647c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
765a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
766a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
7672dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
768fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
769fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int64_t estimatedSize = factor * size;
770fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    CHECK_GE(estimatedSize, 8);
771fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
772fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    return estimatedSize;
7732dec2b5be2056c6d9428897dc672185872d30d17James Dong}
7742dec2b5be2056c6d9428897dc672185872d30d17James Dong
7752dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
776674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
77725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
779fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStartMeta = param;
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
781a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
782a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
783a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
784a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
785a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
786a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
787a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
788a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
789a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
790a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
7912dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
7922dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
7932dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
7942dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
7952dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
7962dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7972dec2b5be2056c6d9428897dc672185872d30d17James Dong
7981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
7991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
8001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
8011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
8021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
8031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
8051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
8061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
807a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
808a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
809d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
810d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
8111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
8121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
8131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
814b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
815b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
816b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
817b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
818b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
8192dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
8202dec2b5be2056c6d9428897dc672185872d30d17James Dong
821de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
822de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
823de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
824de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
825de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
826065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
82793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
828a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
829a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
830a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
83193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
832a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
833a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
834a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
835a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
8368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
8378f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
8388f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
8398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
84043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
8413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
8428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
84377e8ae9967a078770416619e99ddb5b010def312James Dong    /*
84477e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
84577e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
8467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
8477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
84877e8ae9967a078770416619e99ddb5b010def312James Dong     */
84977e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
85077e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
85177e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
85277e8ae9967a078770416619e99ddb5b010def312James Dong
8537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
854720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * mWriteBoxToMemory is true if the amount of data in a file-level meta or
855720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * moov box is smaller than the reserved free space at the beginning of a
856720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * file, AND when the content of the box is constructed. Note that video/
857720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * audio frame data is always written to the file but not in the memory.
8587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
859720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * Before stop()/reset() is called, mWriteBoxToMemory is always
8607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
861720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * file-level meta and/or moov box needs to be constructed.
8627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
863720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * 1) Right before the box is constructed, mWriteBoxToMemory to set to
864720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * mStreamableFile so that if the file is intended to be streamable, it
865720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * is set to true; otherwise, it is set to false. When the value is set
866720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * to false, all the content of that box is written immediately to
8677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
868720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * content of that box is written to an in-memory cache,
869720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * mInMemoryCache, util the following condition happens. Note
8707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
8717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
8727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
873720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * 2) While the data of the box is written to an in-memory
8747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
875720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * If the data size surpasses the reserved space, subsequent box data
876720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * could no longer be hold in the in-memory cache. This also
8777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
878720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * _all_ subsequent box data must be written to the end of the file.
879720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * mWriteBoxToMemory must be set to false to direct the write
8807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
8817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
882720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * 3) If the data size in the box is smaller than the reserved
883720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * space after the box is completely constructed, the in-memory
884720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * cache copy of the box is written to the reserved free space.
885720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * mWriteBoxToMemory is always set to false after all boxes that
886720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * using the in-memory cache have been constructed.
8877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
888720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mWriteBoxToMemory = false;
889720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCache = NULL;
890720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCacheOffset = 0;
8917837c17063a4c50bc856ba59418516fdab731de7James Dong
892fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
893fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    ALOGV("muxer starting: mHasMoovBox %d, mHasFileLevelMeta %d",
894fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mHasMoovBox, mHasFileLevelMeta);
895fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
89720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8987837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
900720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    if (mInMemoryCacheSize == 0) {
9012dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
902fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mHasFileLevelMeta) {
903720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mInMemoryCacheSize += estimateFileLevelMetaSize();
904fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
905fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mHasMoovBox) {
906fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (param) {
907fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                param->findInt32(kKeyBitRate, &bitRate);
908fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
909720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mInMemoryCacheSize += estimateMoovBoxSize(bitRate);
9102dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
9117837c17063a4c50bc856ba59418516fdab731de7James Dong    }
91277e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
91377e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
91477e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
915720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        writeInt32(mInMemoryCacheSize);
91677e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
917720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        mMdatOffset = mFreeBoxOffset + mInMemoryCacheSize;
91877e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
91977e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
92077e8ae9967a078770416619e99ddb5b010def312James Dong    }
9217837c17063a4c50bc856ba59418516fdab731de7James Dong
9227837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
923c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
9241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
9251acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
9261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
9271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
9281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
9291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
9311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
9321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
9331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
936a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
937a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
93820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
9391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
940a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
94125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
9451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
9461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
94837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
9495ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    ALOGW("MPEG4Writer: pause is not supported");
9505ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    return ERROR_UNSUPPORTED;
951a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
952a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
9531c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
954b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
955411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
956411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
957411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
9581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
9601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
9611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
9631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
9641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
9671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
968411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
969b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
9701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
97213f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
97313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
97413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
97513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
97613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
97713f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
97813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
97913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
98013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
98113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
98213f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
98313f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
9843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
98513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
98613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
98713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
98813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
98913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
99013f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
99113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
99213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
99313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
99413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
99513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
99613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
99713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
99813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
99913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
100013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
100113f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
100213f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
100313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
100413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
100513f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
100613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
100713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
100813f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
100913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
101013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
101113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
101213f6284305e4b27395a23db7882d670bdb1bcae1James Dong
101313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
101413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
101513f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
101613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
101713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
101813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
101913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
102013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
102113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
102213f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
102313f6284305e4b27395a23db7882d670bdb1bcae1James Dong
1024411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
1025411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
1026411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
1027411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
1028411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
1029720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    free(mInMemoryCache);
1030720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCache = NULL;
1031411ba422e3635d534928ffd81abf54f4f291c739James Dong}
103213f6284305e4b27395a23db7882d670bdb1bcae1James Dong
1033fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::finishCurrentSession() {
1034fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    reset(false /* stopSource */);
1035fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1036fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1037fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::switchFd() {
1038fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("switchFd");
1039fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock l(mLock);
1040fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mSwitchPending) {
1041fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return OK;
1042fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1043fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1044fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd == -1) {
1045fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGW("No FileDescripter for next recording");
1046fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return INVALID_OPERATION;
1047fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1048fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1049fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSwitchPending = true;
1050fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    sp<AMessage> msg = new AMessage(kWhatSwitch, mReflector);
1051fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    status_t err = msg->post();
1052fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1053fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return err;
1054fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1055fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1056fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::reset(bool stopSource) {
1057674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
105837187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
1059411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
1060411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
1061411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
1062411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
1063411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
1064411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
1065411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
1066411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
1067411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
106820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
106920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107037187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
10718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
107265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
1073fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int32_t nonImageTrackCount = 0;
107420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
1075fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        it != mTracks.end(); ++it) {
1076fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        status_t status = (*it)->stop(stopSource);
107737187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
107837187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
107937187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
108020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1081fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // skip image tracks
1082fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if ((*it)->isHeic()) continue;
1083fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        nonImageTrackCount++;
1084fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
10858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
10868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
10878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
108820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
108965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
109065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
109165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
109265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
109365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
1094fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (nonImageTrackCount > 1) {
1095a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
109665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
109720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
11007837c17063a4c50bc856ba59418516fdab731de7James Dong
110137187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
110237187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
1103411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
110437187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
110537187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
110637187916a486504acaf83bea30147eb5fbf46ae5James Dong
110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
11081acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
1109c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
11101f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
1111c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
11121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
1113c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
11141f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
11151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
1116c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
11171acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
1118c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1120720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    // Construct file-level meta and moov box now
1121720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCacheOffset = 0;
1122720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mWriteBoxToMemory = mStreamableFile;
1123720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    if (mWriteBoxToMemory) {
11247b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
1125720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        // if the file is not streamable.
11267b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1127720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        mInMemoryCache = (uint8_t *) malloc(mInMemoryCacheSize);
1128720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        CHECK(mInMemoryCache != NULL);
11297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
11307837c17063a4c50bc856ba59418516fdab731de7James Dong
1131fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mHasFileLevelMeta) {
1132fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeFileLevelMetaBox();
1133720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        if (mWriteBoxToMemory) {
1134fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeCachedBoxToFile("meta");
1135fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else {
1136fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            ALOGI("The file meta box is written at the end.");
1137fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1138fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
11397837c17063a4c50bc856ba59418516fdab731de7James Dong
1140fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mHasMoovBox) {
1141fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeMoovBox(maxDurationUs);
1142720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        // mWriteBoxToMemory could be set to false in
1143fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // MPEG4Writer::write() method
1144720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        if (mWriteBoxToMemory) {
1145fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeCachedBoxToFile("moov");
1146fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else {
1147fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            ALOGI("The mp4 file will not be streamable.");
1148fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
11497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
1150720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mWriteBoxToMemory = false;
11517837c17063a4c50bc856ba59418516fdab731de7James Dong
1152720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    // Free in-memory cache for box writing
1153720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    if (mInMemoryCache != NULL) {
1154720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        free(mInMemoryCache);
1155720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        mInMemoryCache = NULL;
1156720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        mInMemoryCacheOffset = 0;
11577837c17063a4c50bc856ba59418516fdab731de7James Dong    }
11587837c17063a4c50bc856ba59418516fdab731de7James Dong
11590c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
116020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1161411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
116237187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
116320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1165fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang/*
1166fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang * Writes currently cached box into file.
1167fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang *
1168720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang * Must be called while mWriteBoxToMemory is true, and will not modify
1169720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang * mWriteBoxToMemory. After the call, remaining cache size will be
1170fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang * reduced and buffer offset will be set to the beginning of the cache.
1171fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang */
1172fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeCachedBoxToFile(const char *type) {
1173720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    CHECK(mWriteBoxToMemory);
1174fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1175720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mWriteBoxToMemory = false;
1176720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    // Content of the box is saved in the cache, and the in-memory
1177720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    // box needs to be written to the file in a single shot.
1178fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1179720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    CHECK_LE(mInMemoryCacheOffset + 8, mInMemoryCacheSize);
1180fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1181fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // Cached box
1182fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    lseek64(mFd, mFreeBoxOffset, SEEK_SET);
1183fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mOffset = mFreeBoxOffset;
1184720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    write(mInMemoryCache, 1, mInMemoryCacheOffset);
1185fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1186fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // Free box
1187fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    lseek64(mFd, mOffset, SEEK_SET);
1188fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mFreeBoxOffset = mOffset;
1189720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    writeInt32(mInMemoryCacheSize - mInMemoryCacheOffset);
1190fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    write("free", 4);
1191fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1192720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    // Rewind buffering to the beginning, and restore mWriteBoxToMemory flag
1193720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCacheSize -= mInMemoryCacheOffset;
1194720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCacheOffset = 0;
1195720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mWriteBoxToMemory = true;
1196fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1197fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    ALOGV("dumped out %s box, estimated size remaining %lld",
1198720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            type, (long long)mInMemoryCacheSize);
1199fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
1200fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1201efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
1202b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
1203efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
1204efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
1205efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
12062b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
12072b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
12082b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen        return 0;
12092b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    }
12102b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    uint32_t mpeg4Time = uint32_t(now) + delta;
1211efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
1212efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
1213efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
1214efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
1215efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
1216b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
1217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
1218b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
1219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
1220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
1221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
1223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
1224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
1225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
1226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
1229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
1236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
1237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
1240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
1241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
124207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
124307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
124407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1245fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeMoovLevelMetaBox();
1246230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // Loop through all the tracks to get the global time offset if there is
1247230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // any ctts table appears in a video track.
1248230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t minCttsOffsetTimeUs = kMaxCttsOffsetTimeUs;
1249b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1250230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        it != mTracks.end(); ++it) {
1251fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!(*it)->isHeic()) {
1252fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            minCttsOffsetTimeUs =
1253fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                std::min(minCttsOffsetTimeUs, (*it)->getMinCttsOffsetTimeUs());
1254fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1255230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    }
1256230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    ALOGI("Ajust the moov start time from %lld us -> %lld us",
1257230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang            (long long)mStartTimestampUs,
1258230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang            (long long)(mStartTimestampUs + minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs));
1259230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // Adjust the global start time.
1260230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    mStartTimestampUs += minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs;
1261230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang
1262230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
1263230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        it != mTracks.end(); ++it) {
1264fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!(*it)->isHeic()) {
1265fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            (*it)->writeTrackHeader(mUse32BitOffset);
1266fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1267b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1268b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1269b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1270b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
12712cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1272b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1273b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1274b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1275fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (!param || !param->findInt32(kKeyFileType, &fileType)) {
1276fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        fileType = OUTPUT_FORMAT_MPEG_4;
1277fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
1278fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (fileType != OUTPUT_FORMAT_MPEG_4 && fileType != OUTPUT_FORMAT_HEIF) {
1279b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
12808284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
12818284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
12828284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1283b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
1284fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // Only write "heic" as major brand if the client specified HEIF
1285fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // AND we indeed receive some image heic tracks.
1286fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (fileType == OUTPUT_FORMAT_HEIF && mHasFileLevelMeta) {
1287fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeFourcc("heic");
1288fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else {
1289fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeFourcc("mp42");
1290fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
12918284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1292fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mHasFileLevelMeta) {
1293fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeFourcc("mif1");
1294fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeFourcc("heic");
1295fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1296fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mHasMoovBox) {
1297fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeFourcc("isom");
1298fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeFourcc("mp42");
1299fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
130507ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
130607ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
130707ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
130807ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
130907ec01904613a0bac32caaa8444b4690998faed7James Dong
131007ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
131107ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
131296626b7f9a4e5c9e1e04f7f710383631d1470364Marco Nelissen    if (property_get_bool("rw.media.record.test", false)) {
131307ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
131407ec01904613a0bac32caaa8444b4690998faed7James Dong    }
131507ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
131607ec01904613a0bac32caaa8444b4690998faed7James Dong}
131707ec01904613a0bac32caaa8444b4690998faed7James Dong
131870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
131907ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
132007ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
132107ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
132207ec01904613a0bac32caaa8444b4690998faed7James Dong    }
132307ec01904613a0bac32caaa8444b4690998faed7James Dong
132470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
132570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
132670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
132770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
132870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
132970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
133070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
133170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
133270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
133313aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
133413aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
133513aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
133613aec890216948b0c364f8f92792129d0335f506James Dong}
133713aec890216948b0c364f8f92792129d0335f506James Dong
133813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
133913aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
134013aec890216948b0c364f8f92792129d0335f506James Dong}
134113aec890216948b0c364f8f92792129d0335f506James Dong
134213aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
134313aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
134413aec890216948b0c364f8f92792129d0335f506James Dong}
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1346fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangoff64_t MPEG4Writer::addSample_l(
1347fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        MediaBuffer *buffer, bool usePrefix, size_t *bytesWritten) {
1348c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1350fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (usePrefix) {
1351fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        addMultipleLengthPrefixedSamples_l(buffer);
1352fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    } else {
1353fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ::write(mFd,
1354fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang              (const uint8_t *)buffer->data() + buffer->range_offset(),
1355fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang              buffer->range_length());
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1357fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        mOffset += buffer->range_length();
1358fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1360fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    *bytesWritten = mOffset - old_offset;
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
136503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
136603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
136703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
136803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
136903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
137003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
137103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
137203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
137303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
137403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
137503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
137603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
137703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1378fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) {
137980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset();
138080f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *currentNalStart = dataStart;
138180f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *nextNalStart;
138280f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *data = dataStart;
138380f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t nextNalSize;
1384986274d9c932d0df597d7809761b4cac2ac8e650Hangyu Kuang    size_t searchSize = buffer->range_length();
138580f78b773f92048944a850efb7b60629643370cdPraveen Chavan
138680f78b773f92048944a850efb7b60629643370cdPraveen Chavan    while (getNextNALUnit(&data, &searchSize, &nextNalStart,
138780f78b773f92048944a850efb7b60629643370cdPraveen Chavan            &nextNalSize, true) == OK) {
138810cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar        size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */;
138980f78b773f92048944a850efb7b60629643370cdPraveen Chavan        MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize);
139080f78b773f92048944a850efb7b60629643370cdPraveen Chavan        addLengthPrefixedSample_l(nalBuf);
139180f78b773f92048944a850efb7b60629643370cdPraveen Chavan        nalBuf->release();
139280f78b773f92048944a850efb7b60629643370cdPraveen Chavan
139380f78b773f92048944a850efb7b60629643370cdPraveen Chavan        currentNalStart = nextNalStart;
139480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    }
139580f78b773f92048944a850efb7b60629643370cdPraveen Chavan
139680f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t currentNalOffset = currentNalStart - dataStart;
139780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    buffer->set_range(buffer->range_offset() + currentNalOffset,
139880f78b773f92048944a850efb7b60629643370cdPraveen Chavan            buffer->range_length() - currentNalOffset);
139980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    addLengthPrefixedSample_l(buffer);
140080f78b773f92048944a850efb7b60629643370cdPraveen Chavan}
140180f78b773f92048944a850efb7b60629643370cdPraveen Chavan
1402fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
140330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
140403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1405b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1406b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1407c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1408b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1409c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1410b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1411c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1412b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1413c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1414c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1415c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1416c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1417c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1418b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1419b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1420b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1421b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross        CHECK_LT(length, 65536u);
142230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1423b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1424c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1425b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1426c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1427c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1428b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1429b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
143030ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
143130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
14327837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1433674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
14347837c17063a4c50bc856ba59418516fdab731de7James Dong
14357837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
1436720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    if (mWriteBoxToMemory) {
14377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1438720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        off64_t boxSize = 8 + mInMemoryCacheOffset + bytes;
1439720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        if (boxSize > mInMemoryCacheSize) {
1440720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            // The reserved free space at the beginning of the file is not big
1441720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            // enough. Boxes should be written to the end of the file from now
1442720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            // on, but not to the in-memory cache.
14437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1444720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            // We write partial box that is in the memory to the file first.
1445c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
14467837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
14477837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
14487837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1449674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1450720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            ::write(mFd, mInMemoryCache, mInMemoryCacheOffset);
14517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
1452720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mOffset += (bytes + mInMemoryCacheOffset);
14537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1454720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            // All subsequent boxes will be written to the end of the file.
1455720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mWriteBoxToMemory = false;
14567837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
1457720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            memcpy(mInMemoryCache + mInMemoryCacheOffset, ptr, bytes);
1458720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mInMemoryCacheOffset += bytes;
14597837c17063a4c50bc856ba59418516fdab731de7James Dong        }
14607837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1461674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
14627837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
14637837c17063a4c50bc856ba59418516fdab731de7James Dong    }
14647837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
14657837c17063a4c50bc856ba59418516fdab731de7James Dong}
14667837c17063a4c50bc856ba59418516fdab731de7James Dong
1467e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1468720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mBoxes.push_back(mWriteBoxToMemory?
1469720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mInMemoryCacheOffset: mOffset);
1470e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1471e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1472e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1473e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1474e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
147520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
1476b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_EQ(strlen(fourcc), 4u);
147720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1478720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mBoxes.push_back(mWriteBoxToMemory?
1479720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mInMemoryCacheOffset: mOffset);
148020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
148120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
148220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
148320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
148420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
148520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
14860c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
148720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1488c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
149020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1491720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    if (mWriteBoxToMemory) {
1492720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        int32_t x = htonl(mInMemoryCacheOffset - offset);
1493720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        memcpy(mInMemoryCache + offset, &x, 4);
14947837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1495c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
14967837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
14977837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1498c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
14997837c17063a4c50bc856ba59418516fdab731de7James Dong    }
150020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1503674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
150420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
150520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
150720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1508674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
150920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
151020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
151220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1513674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
151420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
151520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
151720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1518674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
152020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1523674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
1527b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_EQ(strlen(s), 4u);
1528674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
153207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
153307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
153407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
153507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
153607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
153707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
153807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
153907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
154007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
154107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
154207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
154307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
154407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
154507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
154607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
154707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
154807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
154907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
155007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
155107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
155207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
155307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
155407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
155507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
155607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
155707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
155807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
155907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
156007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
156107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
156207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
156307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
156407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
156507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
156607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
156707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
156807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
156907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
157007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
157107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
157207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
157307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
157407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
157507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
157607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
157707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
157807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
157907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
158007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
158107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
158207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
158307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
158407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
158507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
158607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
158707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
158807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
158907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
159007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
159107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
159207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
159307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
159407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
159507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
159607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
159707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
159807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
15997c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
160007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
160107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
160207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1603e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1604e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1605e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1606e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1607e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
16087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
16097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
16107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1611e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1612e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1613e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
16144dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) {
16154dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 9) {
16164dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        return BAD_VALUE;
16174dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
16184dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
16194dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 0) {
16204dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount);
16214dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32;
16224dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
16234dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
16244dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    return OK;
16254dbff11975e737482537e1636051690188f3fbc4Praveen Chavan}
16264dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
1627fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::notifyApproachingLimit() {
1628fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock autolock(mLock);
1629fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // Only notify once.
1630fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mSendNotify) {
1631fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return;
1632fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1633fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGW("Recorded file size is approaching limit %" PRId64 "bytes",
1634fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mMaxFileSizeLimitBytes);
1635fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING, 0);
1636fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSendNotify = true;
1637fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1638fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
163920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1640674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
164120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
164220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
164378a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
164478a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
164578a1a286f736888ae7af8860b2c424af0d978848James Dong}
164678a1a286f736888ae7af8860b2c424af0d978848James Dong
1647d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1648d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1649d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1650d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1651d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1652720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    int64_t nTotalBytesEstimate = static_cast<int64_t>(mInMemoryCacheSize);
1653d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1654d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1655d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1656d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
16571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
165877e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
165977e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
166077e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
166177e8ae9967a078770416619e99ddb5b010def312James Dong    }
1662fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1663acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1664acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1665acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1666acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1667d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1668d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1669fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangbool MPEG4Writer::approachingFileSizeLimit() {
1670fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // No limit
1671fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mMaxFileSizeLimitBytes == 0) {
1672fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return false;
1673fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1674fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1675720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    int64_t nTotalBytesEstimate = static_cast<int64_t>(mInMemoryCacheSize);
1676fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
1677fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         it != mTracks.end(); ++it) {
1678fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1679fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1680fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1681fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (!mStreamableFile) {
1682fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // Add 1024 bytes as error tolerance
1683fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return nTotalBytesEstimate + 1024 >= (90 * mMaxFileSizeLimitBytes) / 100;
1684fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1685fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1686fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return (nTotalBytesEstimate >= (90 * mMaxFileSizeLimitBytes) / 100);
1687fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1688fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1689d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1690d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1691d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1692d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1693d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1694d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1695d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1696d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1697fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!(*it)->isHeic() && (*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1698d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1699d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1700d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1701d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1702d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1703d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
170425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
170525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
170625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
170725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
170825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
170925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
171025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
171125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
171225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
171325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
171425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
171525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
171625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1717f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1718a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
171943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
17203c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1721065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1722f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1723a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
17243c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
17253c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
17263c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1727f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
17283c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
17293c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
17303c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
17313c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
173258ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
173358ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
173458ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
173558ae9c530247668f8af36e30d228c716c226b3d4James Dong}
173658ae9c530247668f8af36e30d228c716c226b3d4James Dong
173720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
173820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
173920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1740ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kang        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
174120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
174225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
174320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
174420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1745a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1746a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1747eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1748fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mGotStartKeyFrame(false),
17499db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang      mIsMalformed(false),
1750bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1751c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1752956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1753be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1754c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1755c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1756c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)),
1757c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)),
1758c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1759c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
1760c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
1761230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang      mMinCttsOffsetTimeUs(0),
1762230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang      mMinCttsOffsetTicks(0),
1763230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang      mMaxCttsOffsetTicks(0),
176420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
176525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1766548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
176713f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
1768a9292fe1c19e8a9b43398ba3d69284c215d7589fRobert Shih      mStartTimestampUs(-1),
1769fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mRotation(0),
1770fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mIsPrimary(0),
1771fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mWidth(0),
1772fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mHeight(0),
177367d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang      mTileWidth(0),
177467d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang      mTileHeight(0),
1775fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mGridRows(0),
1776fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mGridCols(0),
1777fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mNumTiles(1),
1778fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mTileIndex(0) {
177919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
17808f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
17811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
17821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
17831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
17849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
17851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
178625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mIsVideo = !strncasecmp(mime, "video/", 6);
1787fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mIsHeic = !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC);
17881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
17891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
17901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1791b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    // store temporal layer count
179225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo) {
1793b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        int32_t count;
1794b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) {
1795b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar            mOwner->setTemporalLayerCount(count);
1796b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        }
1797b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    }
1798b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar
1799fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (!mIsHeic) {
1800fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        setTimeScale();
1801fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    } else {
1802fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        CHECK(mMeta->findInt32(kKeyWidth, &mWidth) && (mWidth > 0));
1803fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        CHECK(mMeta->findInt32(kKeyHeight, &mHeight) && (mHeight > 0));
1804fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
180567d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang        int32_t tileWidth, tileHeight, gridRows, gridCols;
180667d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang        if (mMeta->findInt32(kKeyTileWidth, &tileWidth) && (tileWidth > 0) &&
180767d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang            mMeta->findInt32(kKeyTileHeight, &tileHeight) && (tileHeight > 0) &&
1808fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mMeta->findInt32(kKeyGridRows, &gridRows) && (gridRows > 0) &&
1809fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mMeta->findInt32(kKeyGridCols, &gridCols) && (gridCols > 0)) {
181067d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang            mTileWidth = tileWidth;
181167d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang            mTileHeight = tileHeight;
1812fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mGridRows = gridRows;
1813fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mGridCols = gridCols;
1814fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mNumTiles = gridRows * gridCols;
1815fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1816fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!mMeta->findInt32(kKeyTrackIsDefault, &mIsPrimary)) {
1817fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mIsPrimary = false;
1818fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1819fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
1820c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1821c059860c73678a202bfa33062723e8f82fb779d9James Dong
1822fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang// Clear all the internal states except the CSD data.
1823fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::Track::resetInternal() {
1824fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mDone = false;
1825fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mPaused = false;
1826fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mResumed = false;
1827fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mStarted = false;
1828fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mGotStartKeyFrame = false;
1829fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mIsMalformed = false;
1830fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mTrackDurationUs = 0;
1831fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mEstimatedTrackSizeBytes = 0;
1832fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mSamplesHaveSameSize = 0;
1833fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStszTableEntries != NULL) {
1834fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStszTableEntries;
1835fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1836fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1837fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1838fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStcoTableEntries != NULL) {
1839fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStcoTableEntries;
1840fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1841fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1842fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mCo64TableEntries != NULL) {
1843fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mCo64TableEntries;
1844fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000);
1845fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1846fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1847fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStscTableEntries != NULL) {
1848fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStscTableEntries;
1849fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000);
1850fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1851fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStssTableEntries != NULL) {
1852fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStssTableEntries;
1853fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1854fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1855fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mSttsTableEntries != NULL) {
1856fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mSttsTableEntries;
1857fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
1858fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1859fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mCttsTableEntries != NULL) {
1860fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mCttsTableEntries;
1861fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
1862fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1863fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mReachedEOS = false;
1864fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1865fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
18661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
1867fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
18681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1869fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (!isHeic() && !mOwner->isFileStreamable()) {
1870fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1871fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                                ? mStcoTableEntries->count()
1872fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                                : mCo64TableEntries->count());
1873fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1874fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
18751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
187678a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
187778a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1878c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1879c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1880c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1881c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
188278a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
188378a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
188478a1a286f736888ae7af8860b2c424af0d978848James Dong    }
18851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
18861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
18871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
18881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
1889fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mStscTableEntries->add(htonl(chunkId));
1890fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mStscTableEntries->add(htonl(sampleId));
1891fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mStscTableEntries->add(htonl(1));
18921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
18931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
18941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1895c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
18961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
18971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
18981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
189979761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
19001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
19015a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1902377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
19035a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1904c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1905c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
19061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
19071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1908965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1909965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1910965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
191125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!mIsVideo) {
1912965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1913965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1914c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1915c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1916965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1917965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1918fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::setNextFd(int fd) {
1919fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("addNextFd");
1920fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock l(mLock);
1921fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mLooper == NULL) {
1922fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mReflector = new AHandlerReflector<MPEG4Writer>(this);
1923fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper = new ALooper;
1924fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper->registerHandler(mReflector);
1925fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper->start();
1926fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1927fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1928fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd != -1) {
1929fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // No need to set a new FD yet.
1930fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return INVALID_OPERATION;
1931fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1932fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mNextFd = fd;
1933fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return OK;
1934fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1935fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1936c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1937fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    CHECK(!mIsHeic);
1938c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1939c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1940c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1941c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1942c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1943c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
19441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
19451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1946fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::Track::addItemOffsetAndSize(off64_t offset, size_t size) {
1947fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    CHECK(mIsHeic);
1948fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1949fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (offset > UINT32_MAX || size > UINT32_MAX) {
1950fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGE("offset or size is out of range: %lld, %lld",
1951fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                (long long) offset, (long long) size);
1952fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        mIsMalformed = true;
1953fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
1954fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mIsMalformed) {
1955fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        return;
1956fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
1957fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mTileIndex >= mNumTiles) {
1958fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGW("Ignoring excess tiles!");
1959fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        return;
1960fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
1961fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
196256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // Rotation angle in HEIF is CCW, framework angle is CW.
196356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    int32_t heifRotation = 0;
196456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    switch(mRotation) {
196556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        case 90: heifRotation = 3; break;
196656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        case 180: heifRotation = 2; break;
196756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        case 270: heifRotation = 1; break;
196856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        default: break; // don't set if invalid
196956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    }
197056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
197156eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    bool hasGrid = (mNumTiles > 1);
197256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
1973fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mProperties.empty()) {
1974fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        mProperties.push_back(mOwner->addProperty_l({
1975fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            .type = FOURCC('h', 'v', 'c', 'C'),
1976fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            .hvcc = ABuffer::CreateAsCopy(mCodecSpecificData, mCodecSpecificDataSize)
1977fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }));
1978fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1979fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        mProperties.push_back(mOwner->addProperty_l({
1980fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            .type = FOURCC('i', 's', 'p', 'e'),
198167d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang            .width = hasGrid ? mTileWidth : mWidth,
198267d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang            .height = hasGrid ? mTileHeight : mHeight,
1983fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }));
198456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
198556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        if (!hasGrid && heifRotation > 0) {
198656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            mProperties.push_back(mOwner->addProperty_l({
198756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                .type = FOURCC('i', 'r', 'o', 't'),
198856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                .rotation = heifRotation,
198956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            }));
199056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        }
1991fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
1992fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1993fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    uint16_t itemId = mOwner->addItem_l({
1994fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        .itemType = "hvc1",
199556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        .isPrimary = hasGrid ? false : (mIsPrimary != 0),
199656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        .isHidden = hasGrid,
1997fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        .offset = (uint32_t)offset,
1998fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        .size = (uint32_t)size,
1999fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        .properties = mProperties,
2000fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    });
2001fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
2002fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mTileIndex++;
200356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    if (hasGrid) {
2004fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        mDimgRefs.push_back(itemId);
2005fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
2006fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mTileIndex == mNumTiles) {
2007fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mProperties.clear();
2008fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mProperties.push_back(mOwner->addProperty_l({
2009fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .type = FOURCC('i', 's', 'p', 'e'),
2010fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .width = mWidth,
2011fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .height = mHeight,
2012fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }));
201356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            if (heifRotation > 0) {
201456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                mProperties.push_back(mOwner->addProperty_l({
201556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                    .type = FOURCC('i', 'r', 'o', 't'),
201656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                    .rotation = heifRotation,
201756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                }));
201856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            }
2019fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mOwner->addItem_l({
2020fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .itemType = "grid",
2021fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .isPrimary = (mIsPrimary != 0),
2022fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .isHidden = false,
2023fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .rows = (uint32_t)mGridRows,
2024fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .cols = (uint32_t)mGridCols,
2025fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .width = (uint32_t)mWidth,
2026fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .height = (uint32_t)mHeight,
2027fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .properties = mProperties,
2028fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .dimgRefs = mDimgRefs,
2029fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            });
2030fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
2031fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
2032fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
2033fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
2034c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
20353856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
2036c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
2037c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
2038c059860c73678a202bfa33062723e8f82fb779d9James Dong
2039c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
2040c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
2041c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
2042c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
2043c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
2044c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
2045c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
2046c059860c73678a202bfa33062723e8f82fb779d9James Dong
2047c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
2048c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
2049c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
2050c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
2051c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
2052c059860c73678a202bfa33062723e8f82fb779d9James Dong
205343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
205419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
205519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
2056fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::onMessageReceived(const sp<AMessage> &msg) {
2057fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    switch (msg->what()) {
2058fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        case kWhatSwitch:
2059fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        {
2060fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            finishCurrentSession();
2061fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mLock.lock();
2062fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            int fd = mNextFd;
2063fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mNextFd = -1;
2064fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mLock.unlock();
20655ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang            initInternal(fd, false /*isFirstSession*/);
2066fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            start(mStartMeta.get());
2067fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mSwitchPending = false;
2068fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED, 0);
2069fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            break;
2070fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2071fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        default:
2072fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        TRESPASS();
2073fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
2074fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
2075fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
207619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
207719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
2078fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
207919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
208019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
20819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint32_t type;
20829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const void *data = NULL;
20839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t size = 0;
208419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
20859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyAVCC, &type, &data, &size);
2086fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC) ||
2087fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang               !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) {
20889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyHVCC, &type, &data, &size);
208919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
209019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
209119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
209219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
2093212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa            if (esds.getCodecSpecificInfo(&data, &size) == OK &&
2094212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa                    data != NULL &&
2095212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa                    copyCodecSpecificData((uint8_t*)data, size) == OK) {
2096212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa                mGotAllCodecSpecificData = true;
209719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
2098212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa            return;
209919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
210019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
21019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
21029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mGotAllCodecSpecificData = true;
21039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
210420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
210520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
210620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
210720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
210820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2109c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
2110c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
2111c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
2112c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
2113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
2114c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
2115c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
2116c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2117c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
2118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
2119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
2120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
2121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
2122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
2123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
2124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
212520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
212620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
212720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
212820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
212920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
213020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
213193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
21323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
213393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
213493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
213593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
213693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
213793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
213893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
2139a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
214093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
214193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
214293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
214393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
214493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
214593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
21461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
21471c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
21483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
21491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
21501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
21511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
21521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
21531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
21541c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
21553856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
21561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
21571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
21581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
21591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
21601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
21611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
21621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
21631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
21641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
21651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
21661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
21671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
21681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
216943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
21701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
21711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2172fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
2173a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
217425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        chunk->mTimeStampUs, chunk->mTrack->getTrackType());
2175fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2176fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
2177fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    bool usePrefix = chunk->mTrack->usePrefix();
2178fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
2179fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
2180fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2181fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        size_t bytesWritten;
2182fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        off64_t offset = addSample_l(*it, usePrefix, &bytesWritten);
2183fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2184fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (chunk->mTrack->isHeic()) {
2185fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            chunk->mTrack->addItemOffsetAndSize(offset, bytesWritten);
2186fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else if (isFirstSample) {
2187fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
2188fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
21891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
21901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
21911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
21921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
2193fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
21941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2195fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
21961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
21971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2198fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
21993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
22001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
220170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
220270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
2203e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
220470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
22051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
220670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
220770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
220870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
22091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
2210377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
22111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
22121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2213fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
22143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
22151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
22171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
22181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
22191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
22201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
22211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
22221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
22231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
22241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
22251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
22261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
22271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
22281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
22303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
2231fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
22321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
22331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
22351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
22361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2237fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
22381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
22391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
22401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
2241fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
2242fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
2243fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
224470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
224570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
224670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
224770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
224870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
224970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
225070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
2251fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
22521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
22531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2254fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2255fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
22561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
22571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22581c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
22593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
22601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2261a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
2262fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2263fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
22641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
2265fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
2266fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
2267fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2268fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
22691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
22701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
22711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2272de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
2273de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
2274de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
2275de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
2276fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
2277de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
2278de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
2279de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
2280fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
2281de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
2282de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
2283de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
2284fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
22851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2286fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2287fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
22881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
22891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22901c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
22913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
22921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
22941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
2295e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
22961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
22971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
22981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
22991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
230070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
230170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
23021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
23031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
23041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
23051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
23061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
23071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
23081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
23091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
2310411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
23111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
23121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
23131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
23141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
231593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
2316a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
2317a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
2318a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
2319a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
2320a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
232125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
232293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
232319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
232419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
232519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
232670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
232719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
232813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
232956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    if ((mIsVideo || mIsHeic) && params &&
233056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            params->findInt32(kKeyRotation, &rotationDegrees)) {
233113f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
233213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
233313f6284305e4b27395a23db7882d670bdb1bcae1James Dong
233493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
233593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2336f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
2337de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
2338a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
2339a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
2340a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
2341a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
2342a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
2343a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
234486b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
234586b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
2346a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
234786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
234886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
234986b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
235086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
235186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
2352a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
2353a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2354a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2355f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
2356a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2357f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
235825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
235925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
236025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
236125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
236220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
236320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
236420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
236520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
236620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
236720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
2368eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
2369c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
237025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
2371956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
23721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
237343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
2374826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    mLastDecodingTimeUs = -1;
237520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
237625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
237720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
237825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
237925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
238020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
238120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
238237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
2383a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
238437187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
2385a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
2386a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2387fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::Track::stop(bool stopSource) {
2388fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGD("%s track stopping. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop");
2389eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
239029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
2391eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
2392eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
2393eaae38445a340c4857c1c5569475879a728e63b7James Dong
239420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
239537187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
239620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
2397f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
2398fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (stopSource) {
2399fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGD("%s track source stopping", getTrackType());
2400fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mSource->stop();
2401fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGD("%s track source stopped", getTrackType());
2402fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
240372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2404f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    // Set mDone to be true after sucessfully stop mSource as mSource may be still outputting
2405f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    // buffers to the writer.
2406f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    mDone = true;
2407f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
240820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
240920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
2410377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
241137187916a486504acaf83bea30147eb5fbf46ae5James Dong
2412fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGD("%s track stopped. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop");
241337187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
241420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
241520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
241625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
241725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
241825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
241925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
242020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
242120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
242220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
242320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
242437187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
2425377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
242620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
242720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
24293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
24303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
24323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
24333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
24343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
24363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
24373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
24393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
24403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
24413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
244247d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar    const uint8_t *nextStartCode = findNextNalStartCode(data, length);
24433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
24443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
244529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
24463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
24473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
24483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
24503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
24513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
245229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
24533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
24543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
24553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
24563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
24573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
24583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
24593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
24603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
24613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
24623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
246307b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                // COULD DO: set profile/level to the lowest required to support all SPSs
246429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
24653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
24663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
24673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
24683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
24693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
24703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
24713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
24723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
24733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
24743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
24763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
24773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
24783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
24803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
24819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 4 + 7);
24829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
24839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
24859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
24869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("copyHEVCCodecSpecificData");
24879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
24899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 23);
24909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
24919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData(
24939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, size_t minLength) {
24949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < minLength) {
2495377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
24963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
24973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
24983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
25009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
25019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
25029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
25039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
25049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = size;
25053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
25063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
25073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
25083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
25103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
25113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
25133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
25143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
25153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
25163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
25173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
25183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
25193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
25203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
25213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
25223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
25233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
25243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
25253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
25263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
25273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
252829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
25293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
25303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
25313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
25323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
25333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
25343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
25353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
25363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
253729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
25383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
25393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
25403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
25413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
25423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
25433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
25443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
254529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
25463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
25473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
25483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
25503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
25513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
25523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
25543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
25553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
25563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
25573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
25583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
25603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
25613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
25623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
256329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
25643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
25653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
25663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
2568377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
25693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
25703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
25713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
25723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
25743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
25753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
25763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
257729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
25783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
25793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
25803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2581377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
25823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
25833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
25843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
25851374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
25861374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
25871374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
25881374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
25893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
25903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
25913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
25923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
25933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
259429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
25953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
25963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
25973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
25981374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
25993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
26003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2601548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
260203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
260303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2604548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
260503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
260629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
260703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
260803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
260903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
26103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2611377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
261203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
261303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
261403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
26153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
26163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
26173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
261803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
261903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
26203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
262103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
262203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
262303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
26243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
26253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
262603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
26279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
26289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
26299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
26309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
26319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
263203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
26333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
26343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
26353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
26363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
263703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
26383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2639b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2640b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2641b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2642b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2643b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
264403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
26453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
26463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
26473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
26483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
26493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
26503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
26513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
26523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
26533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
26543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
26553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
26563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
26573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
26583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
26593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
26603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
26613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
26623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
26633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
26643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
26653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
26663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
26673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
26683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
26693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
26703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
26713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
26723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
26733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
26743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
26753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
267603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
267703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
267803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
267903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
26809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
26819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
26829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, HevcParameterSets &paramSets) {
26839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
26849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("parseHEVCCodecSpecificData");
26859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *tmp = data;
26869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *nextStartCode = data;
26879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t bytesLeft = size;
26889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
268947d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar        nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4);
26909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
26919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (err != OK) {
26929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
26939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
26949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
26959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Move on to find the next parameter set
26969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        bytesLeft -= nextStartCode - tmp;
26979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        tmp = nextStartCode;
26989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
26999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t csdSize = 23;
27019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const size_t numNalUnits = paramSets.getNumNalUnits();
27029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
27039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kMandatoryHevcNalUnitTypes[i];
27049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
27059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets == 0) {
27069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Cound not find NAL unit of type %d", type);
27079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
27089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
27099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
27109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
27119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kHevcNalUnitTypes[i];
27129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
27139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets > 0xffff) {
27149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
27159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
27169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
27179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        csdSize += 3;
27189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (size_t j = 0; j < numNalUnits; ++j) {
27199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (paramSets.getType(j) != type) {
27209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                continue;
27219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
27229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            csdSize += 2 + paramSets.getSize(j);
27239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
27249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
27259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = csdSize;
27269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
27279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
27289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
27309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
27319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData != NULL) {
27339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Already have codec specific data");
27349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
27359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
27369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < 4) {
27389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Codec specific data length too short: %zu", size);
27399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
27409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
27419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Data is in the form of HEVCCodecSpecificData
27439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (memcmp("\x00\x00\x00\x01", data, 4)) {
27449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return copyHEVCCodecSpecificData(data, size);
27459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
27469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    HevcParameterSets paramSets;
27489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
27493d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed parsing codec specific data");
27509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
27519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
27529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificData = malloc(mCodecSpecificDataSize);
27549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
27559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
27569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
27579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
27589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
27599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
27603d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim            &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2);
27619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (err != OK) {
27623d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed constructing HVCC atom");
27639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return err;
27649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
27659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
27679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
27689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
2769872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2770872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2771872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2772872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2773872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2774872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2775872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2776872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2777872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2778872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2779872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2780872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2781872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2782872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2783872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2784872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2785872a481558350634a3fd5cb67939de288af00ecbJames Dong
278662a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuangvoid MPEG4Writer::Track::dumpTimeStamps() {
2787dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    ALOGE("Dumping %s track's last 10 frames timestamp and frame type ", getTrackType());
278862a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    std::string timeStampString;
2789dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    for (std::list<TimestampDebugHelperEntry>::iterator entry = mTimestampDebugHelper.begin();
2790dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang            entry != mTimestampDebugHelper.end(); ++entry) {
2791dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        timeStampString += "(" + std::to_string(entry->pts)+
2792dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang                "us, " + std::to_string(entry->dts) + "us " + entry->frameType + ") ";
279362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    }
279462a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    ALOGE("%s", timeStampString.c_str());
279562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang}
279662a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
279737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
279830ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
279913aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
280043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
280113aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
280213aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
28037c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar    int32_t nActualFrames = 0;        // frames containing non-CSD data (non-0 length)
280413aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2805965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2806965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2807965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2808965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2809965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2810000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2811a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2812965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2813000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2814000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2815000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
281643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2817c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2818e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2819a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2820a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
282125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (mIsVideo) {
2822a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
282325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else {
282425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0);
2825a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2826de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2827de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2828de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2829de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2830985f838934510983d8a887461e98dca60a6e858fJames Dong
2831d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
283220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
283393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
28341889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    MediaBufferBase *buffer;
283525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *trackName = getTrackType();
283693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
283720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
283820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
283920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
284013aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
284120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
284220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
284320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2844a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2845a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2846a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2847a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2848a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2849a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2850a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2851a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2852a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
285330ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
285430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
285503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
28563d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        if (buffer->meta_data().findInt32(kKeyIsCodecConfig, &isCodecConfig)
285703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
28587c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // if config format (at track addition) already had CSD, keep that
28597c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // UNLESS we have not received any frames yet.
28607c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // TODO: for now the entire CSD has to come in one frame for encoders, even though
28617c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // they need to be spread out for decoders.
28627c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            if (mGotAllCodecSpecificData && nActualFrames > 0) {
28637c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                ALOGI("ignoring additional CSD for video track after first frame");
28647c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            } else {
28657c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                mMeta = mSource->getFormat(); // get output format after format change
28666e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                status_t err;
28677c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                if (mIsAvc) {
28686e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                    err = makeAVCCodecSpecificData(
28697c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
28707c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
28717c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
2872fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                } else if (mIsHevc || mIsHeic) {
28736e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                    err = makeHEVCCodecSpecificData(
28747c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
28757c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
28767c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
28777c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsMPEG4) {
28787c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
28797c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
28807c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                }
288130ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
288230ab66297501757d745b9ae10da61adcd891f497Andreas Huber
288330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
288430ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
28856e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang            if (OK != err) {
28866e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                mSource->stop();
28876e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
28886e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                       mTrackId | MEDIA_RECORDER_TRACK_ERROR_GENERAL, err);
28896e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                break;
28906e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang            }
289130ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2892548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
289330ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2894a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2895a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2896e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        // Per-frame metadata sample's size must be smaller than max allowed.
2897fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!mIsVideo && !mIsAudio && !mIsHeic &&
2898fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                buffer->range_length() >= kMaxMetadataSize) {
2899e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            ALOGW("Buffer size is %zu. Maximum metadata buffer size is %lld for %s track",
2900e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang                    buffer->range_length(), (long long)kMaxMetadataSize, trackName);
2901e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            buffer->release();
2902e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            mSource->stop();
2903e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            mIsMalformed = true;
2904e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            break;
2905e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        }
2906e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang
29077c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar        ++nActualFrames;
29087c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
2909d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2910d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2911d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2912d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2913d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2914d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
29153d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        meta_data = new MetaData(buffer->meta_data());
2916d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2917d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2918d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2919fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (usePrefix()) StripStartcode(copy);
2920e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
2921b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
2922fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (usePrefix()) {
2923b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
2924b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
2925b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
2926b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
2927b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
2928b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
2929050b28a593350047845a45a14cc5026221ac1620James Dong
2930d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
29311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
29321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
29331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
2934d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
2935fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            if (mOwner->switchFd() != OK) {
2936fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
2937fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        mOwner->mMaxFileSizeLimitBytes);
2938fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                mSource->stop();
2939fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                mOwner->notify(
2940fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
2941fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            } else {
2942fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                ALOGV("%s Current recorded file size exceeds limit %" PRId64 "bytes. Switching output",
2943fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        getTrackType(), mOwner->mMaxFileSizeLimitBytes);
2944fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            }
2945d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
2946d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2947d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2948fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
2949d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
2950316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
2951316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileDurationLimitUs);
2952d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
2953d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
2954d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
2955d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
2956d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
2957d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
2958fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mOwner->approachingFileSizeLimit()) {
2959fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mOwner->notifyApproachingLimit();
2960fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2961050b28a593350047845a45a14cc5026221ac1620James Dong
2962d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
2963d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
2964d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
2965d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
2966fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // For video, skip the first several non-key frames until getting the first key frame.
2967fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mIsVideo && !mGotStartKeyFrame && !isSync) {
2968fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            ALOGD("Video skip non-key frame");
2969fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            copy->release();
2970fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            continue;
2971fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2972fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mIsVideo && isSync) {
2973fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mGotStartKeyFrame = true;
2974fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2975d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
297648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
2977a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang        if (!mIsHeic) {
2978a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mStszTableEntries->count() == 0) {
2979a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mFirstSampleTimeRealUs = systemTime() / 1000;
2980a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mStartTimestampUs = timestampUs;
2981a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mOwner->setStartTimestampUs(mStartTimestampUs);
2982a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                previousPausedDurationUs = mStartTimestampUs;
298311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
298411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
2985a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mResumed) {
2986a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
2987a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
2988a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    copy->release();
2989a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mSource->stop();
2990a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mIsMalformed = true;
2991a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    break;
2992a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
2993a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
2994a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
2995a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
2996a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    copy->release();
2997a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mSource->stop();
2998a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mIsMalformed = true;
2999a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    break;
3000a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3001a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3002a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                previousPausedDurationUs += pausedDurationUs - lastDurationUs;
3003a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mResumed = false;
3004a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            }
3005a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            TimestampDebugHelperEntry timestampDebugEntry;
3006a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            timestampUs -= previousPausedDurationUs;
3007a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            timestampDebugEntry.pts = timestampUs;
3008a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
300911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
3010d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
30119db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
30129db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
301311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
301411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
3015a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mIsVideo) {
3016a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                /*
3017a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                 * Composition time: timestampUs
3018a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                 * Decoding time: decodingTimeUs
3019a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                 * Composition time offset = composition time - decoding time
3020a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                 */
3021a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                int64_t decodingTimeUs;
3022a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
3023a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                decodingTimeUs -= previousPausedDurationUs;
3024a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3025a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                // ensure non-negative, monotonic decoding time
3026a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mLastDecodingTimeUs < 0) {
3027a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    decodingTimeUs = std::max((int64_t)0, decodingTimeUs);
3028a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                } else {
3029a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // increase decoding time by at least the larger vaule of 1 tick and
3030a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // 0.1 milliseconds. This needs to take into account the possible
3031a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // delta adjustment in DurationTicks in below.
3032a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    decodingTimeUs = std::max(mLastDecodingTimeUs +
3033a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                            std::max(100, divUp(1000000, mTimeScale)), decodingTimeUs);
3034a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
303511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
3036a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mLastDecodingTimeUs = decodingTimeUs;
3037a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                timestampDebugEntry.dts = decodingTimeUs;
3038a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                timestampDebugEntry.frameType = isSync ? "Key frame" : "Non-Key frame";
3039a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                // Insert the timestamp into the mTimestampDebugHelper
3040a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mTimestampDebugHelper.size() >= kTimestampDebugCount) {
3041a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mTimestampDebugHelper.pop_front();
3042a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3043a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mTimestampDebugHelper.push_back(timestampDebugEntry);
3044a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3045a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                cttsOffsetTimeUs =
3046a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
3047a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
3048a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    copy->release();
3049a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mSource->stop();
3050a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mIsMalformed = true;
3051a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    break;
3052a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3053a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3054a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                timestampUs = decodingTimeUs;
3055a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
3056a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    timestampUs, cttsOffsetTimeUs);
3057a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3058a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                // Update ctts box table if necessary
3059a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                currCttsOffsetTimeTicks =
3060a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
3061a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
3062a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    copy->release();
3063a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mSource->stop();
3064a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mIsMalformed = true;
3065a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    break;
3066a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3067a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3068a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mStszTableEntries->count() == 0) {
3069a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // Force the first ctts table entry to have one single entry
3070a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // so that we can do adjustment for the initial track start
3071a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // time offset easily in writeCttsBox().
3072a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
3073a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
3074a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    cttsSampleCount = 0;      // No sample in ctts box is pending
3075a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                } else {
3076a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
3077a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
3078a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
3079a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        cttsSampleCount = 1;  // One sample in ctts box is pending
3080a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    } else {
3081a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        ++cttsSampleCount;
3082a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    }
3083a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3084a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3085a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                // Update ctts time offset range
3086a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mStszTableEntries->count() == 0) {
3087a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mMinCttsOffsetTicks = currCttsOffsetTimeTicks;
3088a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mMaxCttsOffsetTicks = currCttsOffsetTimeTicks;
3089a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                } else {
3090a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    if (currCttsOffsetTimeTicks > mMaxCttsOffsetTicks) {
3091a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        mMaxCttsOffsetTicks = currCttsOffsetTimeTicks;
3092a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTicks) {
3093a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        mMinCttsOffsetTicks = currCttsOffsetTimeTicks;
3094a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        mMinCttsOffsetTimeUs = cttsOffsetTimeUs;
3095a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    }
3096a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3097826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            }
3098826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
3099a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mOwner->isRealTimeRecording()) {
3100a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mIsAudio) {
3101a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    updateDriftTime(meta_data);
3102a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3103dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang            }
3104dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang
3105a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
310611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
3107d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
31089db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
31099db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
311011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
311111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
3112a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
3113a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    trackName, timestampUs, previousPausedDurationUs);
3114a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (timestampUs > mTrackDurationUs) {
3115a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mTrackDurationUs = timestampUs;
3116a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            }
3117000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3118a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // We need to use the time scale based ticks, rather than the
3119a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // timestamp itself to determine whether we have to use a new
3120a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // stts entry, since we may have rounding errors.
3121a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // The calculation is intended to reduce the accumulated
3122a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // rounding errors.
3123a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            currDurationTicks =
3124a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
3125a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
3126a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (currDurationTicks < 0ll) {
3127a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
3128a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        (long long)timestampUs, (long long)lastTimestampUs, trackName);
312911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
3130d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
31319db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
31329db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
313311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
313411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
3135a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // if the duration is different for this sample, see if it is close enough to the previous
3136a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // duration that we can fudge it and use the same value, to avoid filling the stts table
3137a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // with lots of near-identical entries.
3138a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // "close enough" here means that the current duration needs to be adjusted by less
3139a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // than 0.1 milliseconds
3140a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
3141a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
3142a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        + (mTimeScale / 2)) / mTimeScale;
3143a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (deltaUs > -100 && deltaUs < 100) {
3144a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // use previous ticks, and adjust timestamp as if it was actually that number
3145a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // of ticks
3146a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    currDurationTicks = lastDurationTicks;
3147a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    timestampUs += deltaUs;
314843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
314943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
3150a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            mStszTableEntries->add(htonl(sampleSize));
3151a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mStszTableEntries->count() > 2) {
3152a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3153a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                // Force the first sample to have its own stts entry so that
3154a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                // we can adjust its value later to maintain the A/V sync.
3155a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
3156a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    addOneSttsTableEntry(sampleCount, lastDurationTicks);
3157a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    sampleCount = 1;
3158a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                } else {
3159a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    ++sampleCount;
3160000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
31618c460498c028888c533ab442be12b6d4b669b965James Dong
316285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
3163a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mSamplesHaveSameSize) {
3164a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
3165a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mSamplesHaveSameSize = false;
3166a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3167a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                previousSampleSize = sampleSize;
3168be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
3169a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
3170a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    trackName, timestampUs, lastTimestampUs);
3171a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            lastDurationUs = timestampUs - lastTimestampUs;
3172a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            lastDurationTicks = currDurationTicks;
3173a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            lastTimestampUs = timestampUs;
3174a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3175a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (isSync != 0) {
3176a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                addOneStssTableEntry(mStszTableEntries->count());
3177be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
3178d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
3179a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mTrackingProgressStatus) {
3180a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mPreviousTrackTimeUs <= 0) {
3181a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mPreviousTrackTimeUs = mStartTimestampUs;
3182a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3183a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                trackProgressStatus(timestampUs);
318493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
318593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
318643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
3187fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            size_t bytesWritten;
3188fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            off64_t offset = mOwner->addSample_l(copy, usePrefix(), &bytesWritten);
3189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
3190fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (mIsHeic) {
3191fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                addItemOffsetAndSize(offset, bytesWritten);
3192fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            } else {
3193fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                uint32_t count = (mOwner->use32BitFileOffset()
3194fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                            ? mStcoTableEntries->count()
3195fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                            : mCo64TableEntries->count());
3196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
3197fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                if (count == 0) {
3198fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                    addChunkOffset(offset);
3199fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                }
320058ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
320158ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
320258ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
320358ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
320458ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
320513aec890216948b0c364f8f92792129d0335f506James Dong
320613aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
3207fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mIsHeic) {
3208fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            bufferChunk(0 /*timestampUs*/);
3209fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            ++nChunks;
3210fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else if (interleaveDurationUs == 0) {
32111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
32121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
321313aec890216948b0c364f8f92792129d0335f506James Dong        } else {
321413aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
321513aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
321613aec890216948b0c364f8f92792129d0335f506James Dong            } else {
321743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
321843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
321943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
322043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
322143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
322213aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
322313aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
3224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
3225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
3226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
322713aec890216948b0c364f8f92792129d0335f506James Dong                    }
32281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
322913aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
323013aec890216948b0c364f8f92792129d0335f506James Dong                }
323113aec890216948b0c364f8f92792129d0335f506James Dong            }
323213aec890216948b0c364f8f92792129d0335f506James Dong        }
323313aec890216948b0c364f8f92792129d0335f506James Dong
323420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
323525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
323645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
323762a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang        dumpTimeStamps();
3238690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
3239f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
324045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
3241bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
3242be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
3243fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mIsHeic) {
3244fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!mChunkSamples.empty()) {
3245fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            bufferChunk(0);
3246fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            ++nChunks;
3247fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
3248be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
3249fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // Last chunk
3250fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!hasMultipleTracks) {
3251fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            addOneStscTableEntry(1, mStszTableEntries->count());
3252fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else if (!mChunkSamples.empty()) {
3253fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            addOneStscTableEntry(++nChunks, mChunkSamples.size());
3254fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            bufferChunk(timestampUs);
3255fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
3256a472613aec322e25891abf5c77bf3f7e3c244920James Dong
3257fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // We don't really know how long the last frame lasts, since
3258fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // there is no frame time after it, just repeat the previous
3259fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // frame's duration.
3260fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mStszTableEntries->count() == 1) {
3261fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            lastDurationUs = 0;  // A single sample's duration
3262fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            lastDurationTicks = 0;
3263fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else {
3264fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            ++sampleCount;  // Count for the last sample
3265fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
3266fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
3267fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mStszTableEntries->count() <= 2) {
3268fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            addOneSttsTableEntry(1, lastDurationTicks);
3269fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (sampleCount - 1 > 0) {
3270fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
3271fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
3272fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else {
3273fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            addOneSttsTableEntry(sampleCount, lastDurationTicks);
3274a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
3275a472613aec322e25891abf5c77bf3f7e3c244920James Dong
3276fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // The last ctts box may not have been written yet, and this
3277fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // is to make sure that we write out the last ctts box.
3278fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
3279fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (cttsSampleCount > 0) {
3280fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
3281fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
328243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
328343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
3284fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        mTrackDurationUs += lastDurationUs;
3285fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
328625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
328743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
328843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
328943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
3290df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
329111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
3292872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
3293a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
3294872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
3295365a963142093a1cd8efdcea76b5f65096a5b115James Dong
329637187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
329737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
329837187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
329937187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
3300365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
3301365a963142093a1cd8efdcea76b5f65096a5b115James Dong
330245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
33039db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    if (mIsMalformed) {
33049db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang        return true;
33059db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    }
33069db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang
3307fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (!mIsHeic && mStszTableEntries->count() == 0) {  // no samples written
330829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
330945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
331045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
331145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
331225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo && mStssTableEntries->count() == 0) {  // no sync frames for video
331329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
331445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
331545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
331645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
331745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
331845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
331945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
332045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
332145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
332245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
332345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
332443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
332507ec01904613a0bac32caaa8444b4690998faed7James Dong
332607ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
332707ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
332807ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
332907ec01904613a0bac32caaa8444b4690998faed7James Dong    }
333007ec01904613a0bac32caaa8444b4690998faed7James Dong
333143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
333243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
333343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
333443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
333525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                    mIsAudio ? 0: 1);
333643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
333743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
333843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
333943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
334043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
334143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
334243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
3343c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
334443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
334586b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
334686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
334786b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
334886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
334986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
335086b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
335186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
335286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
335386b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
335486b7f47aa7482424cf8fd248f1315311919be3b0James Dong
335586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
335670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
335770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
335886b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
335970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
336007ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
336107ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
336207ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
336307ec01904613a0bac32caaa8444b4690998faed7James Dong
336443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
336543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
336643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
336743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
336870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
336970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
337070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
337170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
337270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
337370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
337470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
337570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
337643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
337743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
337843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
3379faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
3380a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
3381c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
3382215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
3383215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
3384a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
3385bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
338693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
338793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
338893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
338993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
3390faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
3391bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
3392faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
3393bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
3394faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3395faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
3396faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
3397faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
3398bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
3399bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
3400faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
3401faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
3402faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
3403faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3404faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
3405faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
3406bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
3407bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
3408faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
3409faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
3410faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
3411bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
3412bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
3413faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
3414faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
3415faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
3416faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3417d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
3418a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
3419e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
3420d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
3421e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
3422e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
3423e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
3424a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
3425e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
3426e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
3427e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
3428e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
3429de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
3430de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
3431de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
3432de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
3433b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
3434b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
3435b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
3436b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
34371c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
34383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
34391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
34401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
34411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
344213aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
344320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
344420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34453b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
3446230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    return mTrackDurationUs + getStartTimeOffsetTimeUs();
344720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
344820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3449d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
3450d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
3451d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
3452d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
3453fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangint32_t MPEG4Writer::Track::getMetaSizeIncrease() const {
3454fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    CHECK(mIsHeic);
345556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
345656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    int32_t grid = (mNumTiles > 1);
345756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
345856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // Note that the rotation angle is in the file meta, and we don't have
345956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // it until start, so here the calculation has to assume rotation.
346056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
346156eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // increase to ipco
346256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    int32_t increase = 20 * (grid + 1)              // 'ispe' property
346356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                     + (8 + mCodecSpecificDataSize) // 'hvcC' property
346456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                     + 9;                           // 'irot' property (worst case)
346556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
346656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // increase to iref and idat
346756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    if (grid) {
346856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        increase += (8 + 2 + 2 + mNumTiles * 2)  // 'dimg' in iref
346956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                  + 12;                          // ImageGrid in 'idat' (worst case)
347056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    }
347156eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
347256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // increase to iloc, iinf and ipma
347356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    increase += (16             // increase to 'iloc'
347456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang              + 21              // increase to 'iinf'
347556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang              + (3 + 2 * 2))    // increase to 'ipma' (worst case, 2 props x 2 bytes)
347656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang              * (mNumTiles + grid);
347756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
347856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // adjust to ipma:
347956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // if rotation is present and only one tile, it could ref 3 properties
348056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    if (!grid) {
348156eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        increase += 2;
348256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    }
348356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
348456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    return increase;
3485fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
3486fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
3487690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
3488690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
3489690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
3490690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
3491690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
34929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
3493fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime) ||
3494fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        !strcasecmp(MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, mime)) {
3495690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
3496690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
349729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
3498690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
3499690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
3500690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
3501690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
3502690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
350329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
3504690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
3505690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
3506690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
3507690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
3508690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
3509690f546b0ee548dbfe997df36418e5302ec2d786James Dong
351025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangconst char *MPEG4Writer::Track::getTrackType() const {
3511fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    return mIsAudio ? "Audio" :
3512fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang           mIsVideo ? "Video" :
3513fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang           mIsHeic  ? "Image" :
3514fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                      "Metadata";
351525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
35168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
351725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
3518efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
3519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
3520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
3521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
3522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
3523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
3524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
3525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
3526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
352725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                } else if (mIsVideo) {
3528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
352925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                } else {
353025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                    writeNmhdBox();
3531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
3532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
3533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
3534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
3535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
3536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
3537b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3539230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuangint64_t MPEG4Writer::Track::getMinCttsOffsetTimeUs() {
3540230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // For video tracks with ctts table, this should return the minimum ctts
3541230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // offset in the table. For non-video tracks or video tracks without ctts
3542230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // table, this will return kMaxCttsOffsetTimeUs.
3543230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
3544230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        return kMaxCttsOffsetTimeUs;
3545230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    }
3546230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    return mMinCttsOffsetTimeUs;
3547230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang}
3548230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang
3549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
3550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
3551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
3552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
3553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
3554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
3555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
355625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (mIsVideo) {
3557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
355825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else {
355925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        writeMetadataFourCCBox();
3560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3561b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
3562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
356325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo) {
356425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        writeCttsBox();
3565b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
3566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
3568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
3569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
3570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
3571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
357325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeMetadataFourCCBox() {
357425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *mime;
357525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    bool success = mMeta->findCString(kKeyMIMEType, &mime);
357625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    CHECK(success);
357725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *fourcc = getFourCCForMime(mime);
357825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (fourcc == NULL) {
357925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Unknown mime type '%s'.", mime);
358025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
358125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
358225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->beginBox(fourcc);    // TextMetaDataSampleEntry
358325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeCString(mime);  // metadata mime_format
358425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->endBox(); // mett
358525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
358625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
3587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
3588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
35918b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
35928b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
359329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
359425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
3595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
35978b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    mOwner->beginBox(fourcc);        // video format
3598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
3601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
3608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
3609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
3610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
3613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
3614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
3615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
3616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
3618c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
3619c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
3620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
3621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
3622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
3624b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
3625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
3626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
3627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
3628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
36299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
36309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        writeHvccBox();
3631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
363458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    writeColrBox();
3635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
3636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
363858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() {
363958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    ColorAspects aspects;
364058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    memset(&aspects, 0, sizeof(aspects));
364158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    // TRICKY: using | instead of || because we want to execute all findInt32-s
364258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
364358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
364458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
364558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
364658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t primaries, transfer, coeffs;
364758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        bool fullRange;
364858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorUtils::convertCodecColorAspectsToIsoAspects(
364958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                aspects, &primaries, &transfer, &coeffs, &fullRange);
365058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->beginBox("colr");
365158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeFourcc("nclx");
365258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(primaries);
365358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(transfer);
365458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(coeffs);
3655fffb0c8fbe16ac948619b85e1eea9e65a9daa0c9Pirama Arumuga Nainar        mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0));
365658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->endBox(); // colr
365758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
365858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar}
365958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
3660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
3661b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
36648b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
36658b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
366629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
366725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
3668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
3671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
3674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
3677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
3678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
3679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
3680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
3684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
3685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
3687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
3688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
3689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
3690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
3691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
3692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
3697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3698b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
3699b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GT(mCodecSpecificDataSize, 0u);
3700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
3702b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_LT(mCodecSpecificDataSize + 23, 128u);
3703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
3705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
3706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
3708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
3709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
3711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
3713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
3714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
371646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt8(0x00);   // buffer size 24-bit (0x300)
371746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
371896bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
371946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
372096bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
372146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
372246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
372346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
3724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
3726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
3740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
3741b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GT(mCodecSpecificDataSize, 0u);
3742bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3743bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan    // Make sure all sizes encode to a single byte.
3744b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_LT(23 + mCodecSpecificDataSize, 128u);
3745bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
3749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
3751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
3753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
3754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
3756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
3758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
3759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
376146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        0x01, 0x77, 0x00, // buffer size 96000 bytes
3762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
3764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
376596bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
376646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
376796bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
376846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
376946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
377046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
377146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
3772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
3773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3787efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
3788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
3789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
3790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
3791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
3792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3794219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
3795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
37968f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
3797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
3798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
3799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
3800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
3801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
3804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
3805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
3806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
3807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
380920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
381025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!mIsVideo) {
3811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
3814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
3815467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        bool success = mMeta->findInt32(kKeyDisplayWidth, &width);
3816467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        success = success && mMeta->findInt32(kKeyDisplayHeight, &height);
3817467743d462773ada299148ed5a210479affd1f4cHangyu Kuang
3818467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        // Use width/height if display width/height are not present.
3819467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        if (!success) {
3820467743d462773ada299148ed5a210479affd1f4cHangyu Kuang            success = mMeta->findInt32(kKeyWidth, &width);
3821467743d462773ada299148ed5a210479affd1f4cHangyu Kuang            success = success && mMeta->findInt32(kKeyHeight, &height);
3822467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        }
3823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
3824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
3826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
3827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
3829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
3832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
3833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
3834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
3835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
3836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
3842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
3843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
3844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
3845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
384925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeNmhdBox() {
385025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->beginBox("nmhd");
385125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeInt32(0);           // version=0, flags=0
385225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->endBox();
385325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
385425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
3855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
3856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
3857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
385925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeFourcc(mIsAudio ? "soun" : (mIsVideo ? "vide" : "meta"));  // component subtype
3860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3863b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
386425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeCString(mIsAudio ? "SoundHandle": (mIsVideo ? "VideoHandle" : "MetadHandle"));
3865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3868efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
38701d515f4b608f1e6592780365857855962c0da725xiahong.bao    int64_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
38721d515f4b608f1e6592780365857855962c0da725xiahong.bao
38731d515f4b608f1e6592780365857855962c0da725xiahong.bao    if (mdhdDuration > UINT32_MAX) {
38741d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32((1 << 24));            // version=1, flags=0
38751d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt64((int64_t)now);         // creation time
38761d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt64((int64_t)now);         // modification time
38771d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(mTimeScale);           // media timescale
38781d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt64(mdhdDuration);         // media timescale
38791d515f4b608f1e6592780365857855962c0da725xiahong.bao    } else {
38801d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(0);                      // version=0, flags=0
38811d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(now);                    // creation time
38821d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(now);                    // modification time
38831d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(mTimeScale);             // media timescale
38841d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32((int32_t)mdhdDuration);  // use media timescale
38851d515f4b608f1e6592780365857855962c0da725xiahong.bao    }
3886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
3887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
3888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
3889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
3890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
3891decc50efede28c5d73137c30d1a95d72dd405555David Yeh    const char *lang = NULL;
3892decc50efede28c5d73137c30d1a95d72dd405555David Yeh    int16_t langCode = 0;
3893decc50efede28c5d73137c30d1a95d72dd405555David Yeh    if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) {
3894decc50efede28c5d73137c30d1a95d72dd405555David Yeh        langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f);
3895decc50efede28c5d73137c30d1a95d72dd405555David Yeh    }
3896decc50efede28c5d73137c30d1a95d72dd405555David Yeh    mOwner->writeInt16(langCode);      // language code
3897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
3898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
3902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
3903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
3904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
3905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
3906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
3907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
3908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
3909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
3913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
3914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
3915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
3916b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
3917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
3918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
3921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
3922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
3924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
3925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
3926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
3929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
3930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
3931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
3932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
3935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
3936b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GE(mCodecSpecificDataSize, 5u);
3937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
3939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
3940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
3941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
3942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
3943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
3945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
39479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
39489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() {
39499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK(mCodecSpecificData);
3950b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GE(mCodecSpecificDataSize, 5u);
39519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
39529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Patch avcc's lengthSize field to match the number
39539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // of bytes we use to indicate the size of a nal unit.
39549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
39559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
39569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->beginBox("hvcC");
39579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
39589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->endBox();  // hvcC
39599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
39609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
3961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
3962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
3963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
3964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
3965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
3966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
3967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
3968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
3971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
3972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
3973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
3974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
3975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
3976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3978230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuangint64_t MPEG4Writer::Track::getStartTimeOffsetTimeUs() const {
3979a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
3980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
3981a9292fe1c19e8a9b43398ba3d69284c215d7589fRobert Shih    if (mStartTimestampUs != -1 && mStartTimestampUs != moovStartTimeUs) {
398243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
3983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
3984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
39856a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih    return trackStartTimeOffsetUs;
39866a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih}
39876a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih
39886a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shihint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
3989230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    return (getStartTimeOffsetTimeUs() * mTimeScale + 500000LL) / 1000000LL;
3990000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
3991000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3992000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
3993000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
3994000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
3995230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
3996230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // For non-vdeio tracks or video tracks without ctts table,
3997230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // adjust duration of first sample for tracks to account for
3998230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // first sample not starting at the media start time.
3999230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // TODO: consider signaling this using some offset
4000230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // as this is not quite correct.
4001230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        uint32_t duration;
4002230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        CHECK(mSttsTableEntries->get(duration, 1));
4003230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        duration = htonl(duration);  // Back to host byte order
4004230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
4005230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    }
4006c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
4007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
4008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
400920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4010965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
4011000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
4012230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
4013000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
4014000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
4015000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
4016965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
4017c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
4018965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
4019965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
4020965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
4021a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
4022230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang            mCttsTableEntries->count(), mMinCttsOffsetTicks, mMaxCttsOffsetTicks);
4023965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
4024965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
4025000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
4026230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t deltaTimeUs = kMaxCttsOffsetTimeUs - getStartTimeOffsetTimeUs();
4027230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t delta = (deltaTimeUs * mTimeScale + 500000LL) / 1000000LL;
4028c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) {
4029c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // entries are <count, ctts> pairs; adjust only ctts
4030c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t duration = htonl(value[1]); // back to host byte order
40310d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        // Prevent overflow and underflow
40320d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        if (delta > duration) {
40330d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka            duration = 0;
40340d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        } else if (delta < 0 && UINT32_MAX + delta < duration) {
40350d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka            duration = UINT32_MAX;
40360d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        } else {
40370d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka            duration -= delta;
40380d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        }
40390d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        value[1] = htonl(duration);
4040c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    });
4041c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
4042965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
4043965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
4044965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
4045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
4046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
4047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
4048c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
4049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
4050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
405125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
4052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
4053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
4054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
4055c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
4056c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
4057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
4058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
405920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
4061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
4062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
4063c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
4064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
4065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
406620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
4068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
4069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
4070c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
4071c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
4072c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
4073c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
4074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
4075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
407620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
407720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
407807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
407907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
408007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
408107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
408207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
408307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
4084fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeHdlr(const char *handlerType) {
4085e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
4086e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
4087e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
4088fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeFourcc(handlerType);
4089e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
4090e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
4091e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
4092e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
4093e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
4094e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
4095e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4096e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
4097e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
4098e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4099e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
4100e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
4101e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
4102e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
4103e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
4104e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
4105e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
4106e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
4107e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
4108e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
4109e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
4110e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
4111e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
4112e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4113e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
4114e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
4115e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4116e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
4117e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
4118e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
4119e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
4120e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
4121e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
4122e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
41237c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
41247c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
41257c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
41267c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
41277c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
41287c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
41297c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
41307c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
41317c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
41327c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
4133e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
4134e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
4135e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
4136e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
41377c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
41387c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
4139e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
4140e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
4141e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
4142e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4143e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
4144e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
4145e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
4146e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
41477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
41487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
4149e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
4150e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
4151e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
4152e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4153e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
4154e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
4155e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
41567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
41577c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
4158e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
4159e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
4160e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
4161e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
4162e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
4163e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
4164e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
4165e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
4166e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
4167e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4168fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeMoovLevelMetaBox() {
4169e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
4170e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
4171e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
4172e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
4173e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4174e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
4175fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeHdlr("mdta");
4176e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
4177e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
4178e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
4179e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
4180e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4181fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIlocBox() {
4182fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("iloc");
4183fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // Use version 1 to allow construction method 1 that refers to
4184fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // data in idat box inside meta box.
4185fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(0x01000000); // Version = 1, Flags = 0
4186fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt16(0x4400);     // offset_size = length_size = 4
4187fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                            // base_offset_size = index_size = 0
4188fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4189fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // 16-bit item_count
4190fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    size_t itemCount = mItems.size();
4191fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (itemCount > 65535) {
4192fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGW("Dropping excess items: itemCount %zu", itemCount);
4193fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        itemCount = 65535;
4194fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4195fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt16((uint16_t)itemCount);
4196fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4197fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (size_t i = 0; i < itemCount; i++) {
4198fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInt16(mItems[i].itemId);
4199fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        bool isGrid = mItems[i].isGrid();
4200fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4201fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInt16(isGrid ? 1 : 0); // construction_method
4202fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInt16(0); // data_reference_index = 0
4203fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInt16(1); // extent_count = 1
4204fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4205fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (isGrid) {
4206fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            // offset into the 'idat' box
4207fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt32(mNumGrids++ * 8);
4208fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt32(8);
4209fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else {
4210fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt32(mItems[i].offset);
4211fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt32(mItems[i].size);
4212fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4213fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4214fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4215fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4216fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4217fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeInfeBox(
4218fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        uint16_t itemId, const char *itemType, uint32_t flags) {
4219fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("infe");
4220fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(0x02000000 | flags); // Version = 2, Flags = 0
4221fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt16(itemId);
4222fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt16(0);          //item_protection_index = 0
4223fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeFourcc(itemType);
4224fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeCString("");       // item_name
4225fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4226fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4227fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4228fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIinfBox() {
4229fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("iinf");
4230fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(0);          // Version = 0, Flags = 0
4231fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4232fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // 16-bit item_count
4233fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    size_t itemCount = mItems.size();
4234fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (itemCount > 65535) {
4235fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGW("Dropping excess items: itemCount %zu", itemCount);
4236fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        itemCount = 65535;
4237fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4238fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4239fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt16((uint16_t)itemCount);
4240fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (size_t i = 0; i < itemCount; i++) {
4241fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInfeBox(mItems[i].itemId, mItems[i].itemType,
4242fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                mItems[i].isHidden ? 1 : 0);
4243fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4244fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4245fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4246fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4247fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4248fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIdatBox() {
4249fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("idat");
4250fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4251fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (size_t i = 0; i < mItems.size(); i++) {
4252fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mItems[i].isGrid()) {
4253fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt8(0); // version
4254fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            // flags == 1 means 32-bit width,height
4255fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            int8_t flags = (mItems[i].width > 65535 || mItems[i].height > 65535);
4256fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt8(flags);
4257fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt8(mItems[i].rows - 1);
4258fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt8(mItems[i].cols - 1);
4259fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (flags) {
4260fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt32(mItems[i].width);
4261fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt32(mItems[i].height);
4262fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            } else {
4263fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt16((uint16_t)mItems[i].width);
4264fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt16((uint16_t)mItems[i].height);
4265fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
4266fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4267fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4268fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4269fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4270fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4271fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4272fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIrefBox() {
4273fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("iref");
4274fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(0);          // Version = 0, Flags = 0
4275fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    {
4276fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        for (size_t i = 0; i < mItems.size(); i++) {
4277fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (!mItems[i].isGrid()) {
4278fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                continue;
4279fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
4280fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            beginBox("dimg");
4281fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt16(mItems[i].itemId);
4282fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            size_t refCount = mItems[i].dimgRefs.size();
4283fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (refCount > 65535) {
4284fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                ALOGW("too many entries in dimg");
4285fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                refCount = 65535;
4286fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
4287fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt16((uint16_t)refCount);
4288fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            for (size_t refIndex = 0; refIndex < refCount; refIndex++) {
4289fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt16(mItems[i].dimgRefs[refIndex]);
4290fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
4291fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            endBox();
4292fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4293fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4294fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4295fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4296fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4297fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writePitmBox() {
4298fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("pitm");
4299fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(0);          // Version = 0, Flags = 0
4300fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt16(mPrimaryItemId);
4301fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4302fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4303fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4304fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIpcoBox() {
4305fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("ipco");
4306fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    size_t numProperties = mProperties.size();
4307fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (numProperties > 32767) {
4308fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGW("Dropping excess properties: numProperties %zu", numProperties);
4309fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        numProperties = 32767;
4310fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4311fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (size_t propIndex = 0; propIndex < numProperties; propIndex++) {
431256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        switch (mProperties[propIndex].type) {
431356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            case FOURCC('h', 'v', 'c', 'C'):
431456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            {
431556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                beginBox("hvcC");
431656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                sp<ABuffer> hvcc = mProperties[propIndex].hvcc;
431756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                // Patch avcc's lengthSize field to match the number
431856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                // of bytes we use to indicate the size of a nal unit.
431956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                uint8_t *ptr = (uint8_t *)hvcc->data();
432056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                ptr[21] = (ptr[21] & 0xfc) | (useNalLengthFour() ? 3 : 1);
432156eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                write(hvcc->data(), hvcc->size());
432256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                endBox();
432356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                break;
432456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            }
432556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            case FOURCC('i', 's', 'p', 'e'):
432656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            {
432756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                beginBox("ispe");
432856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                writeInt32(0); // Version = 0, Flags = 0
432956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                writeInt32(mProperties[propIndex].width);
433056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                writeInt32(mProperties[propIndex].height);
433156eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                endBox();
433256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                break;
433356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            }
433456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            case FOURCC('i', 'r', 'o', 't'):
433556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            {
433656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                beginBox("irot");
433756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                writeInt8(mProperties[propIndex].rotation);
433856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                endBox();
433956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                break;
434056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            }
434156eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            default:
434256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                ALOGW("Skipping unrecognized property: type 0x%08x",
434356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                        mProperties[propIndex].type);
4344fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4345fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4346fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4347fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4348fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4349fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIpmaBox() {
4350fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("ipma");
4351fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    uint32_t flags = (mProperties.size() > 127) ? 1 : 0;
4352fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(flags); // Version = 0
4353fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4354fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(mAssociationEntryCount);
4355fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (size_t itemIndex = 0; itemIndex < mItems.size(); itemIndex++) {
4356fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        const Vector<uint16_t> &properties = mItems[itemIndex].properties;
4357fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (properties.empty()) {
4358fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            continue;
4359fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4360fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInt16(mItems[itemIndex].itemId);
4361fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4362fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        size_t entryCount = properties.size();
4363fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (entryCount > 255) {
4364fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            ALOGW("Dropping excess associations: entryCount %zu", entryCount);
4365fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            entryCount = 255;
4366fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4367fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInt8((uint8_t)entryCount);
4368fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        for (size_t propIndex = 0; propIndex < entryCount; propIndex++) {
4369fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (flags & 1) {
4370fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt16((1 << 15) | properties[propIndex]);
4371fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            } else {
4372fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt8((1 << 7) | properties[propIndex]);
4373fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
4374fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4375fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4376fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4377fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4378fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4379fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIprpBox() {
4380fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("iprp");
4381fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeIpcoBox();
4382fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeIpmaBox();
4383fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4384fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4385fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4386fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeFileLevelMetaBox() {
4387fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mItems.empty()) {
4388fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGE("no valid item was found");
4389fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        return;
4390fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4391fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4392fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // patch up the mPrimaryItemId and count items with prop associations
4393a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang    uint16_t firstVisibleItemId = 0;
4394fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (size_t index = 0; index < mItems.size(); index++) {
4395fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mItems[index].isPrimary) {
4396fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mPrimaryItemId = mItems[index].itemId;
4397a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang        } else if (!firstVisibleItemId && !mItems[index].isHidden) {
4398a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            firstVisibleItemId = mItems[index].itemId;
4399fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4400fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4401fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!mItems[index].properties.empty()) {
4402fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mAssociationEntryCount++;
4403fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4404fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4405fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4406fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mPrimaryItemId == 0) {
4407a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang        if (firstVisibleItemId > 0) {
4408a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            ALOGW("didn't find primary, using first visible item");
4409a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            mPrimaryItemId = firstVisibleItemId;
4410a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang        } else {
4411a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            ALOGW("no primary and no visible item, using first item");
4412a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            mPrimaryItemId = mItems[0].itemId;
4413a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang        }
4414fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4415fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4416fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("meta");
4417fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(0); // Version = 0, Flags = 0
4418fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeHdlr("pict");
4419fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeIlocBox();
4420fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeIinfBox();
4421fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writePitmBox();
4422fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeIprpBox();
4423fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mNumGrids > 0) {
4424fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeIdatBox();
4425fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeIrefBox();
4426fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4427fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4428fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4429fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4430fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhanguint16_t MPEG4Writer::addProperty_l(const ItemProperty &prop) {
4431fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    char typeStr[5];
4432fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    MakeFourCCString(prop.type, typeStr);
4433fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    ALOGV("addProperty_l: %s", typeStr);
4434fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4435fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mProperties.push_back(prop);
4436fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4437fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // returning 1-based property index
4438fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    return mProperties.size();
4439fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4440fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4441fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhanguint16_t MPEG4Writer::addItem_l(const ItemInfo &info) {
4442fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    ALOGV("addItem_l: type %s, offset %u, size %u",
4443fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            info.itemType, info.offset, info.size);
4444fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4445fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    size_t index = mItems.size();
4446fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mItems.push_back(info);
4447fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4448fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // make the item id start at 10000
4449fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mItems.editItemAt(index).itemId = index + 10000;
4450fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4451fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang#if (LOG_NDEBUG==0)
4452fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (!info.properties.empty()) {
4453fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        AString str;
4454fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        for (size_t i = 0; i < info.properties.size(); i++) {
4455fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (i > 0) {
4456fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                str.append(", ");
4457fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
4458fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            str.append(info.properties[i]);
4459fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4460fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGV("addItem_l: id %d, properties: %s", mItems[index].itemId, str.c_str());
4461fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4462fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang#endif // (LOG_NDEBUG==0)
4463fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4464fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    return mItems[index].itemId;
4465fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4466fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
446707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
446807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
446907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
447007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
447107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
447207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
447307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
447407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
447507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
4476432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
4477432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
447807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
447907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
448007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
448107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
448207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
448307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
448407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
448507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
448620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
4487