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;
8699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhangstatic const int kItemIdBase = 10000;
8799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhangstatic const char kExifHeader[] = {'E', 'x', 'i', 'f', '\0', '\0'};
8899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhangstatic const int32_t kTiffHeaderOffset = htonl(sizeof(kExifHeader));
8962a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = {
919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = {
969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePrefixSei,
1009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSuffixSei,
1019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
102da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang/* uncomment to include build in meta */
1037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1
1047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track {
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
107ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kang    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
1088f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    ~Track();
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t start(MetaData *params);
112fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    status_t stop(bool stopSource = true);
11337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t pause();
11425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool reachedEOS();
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1163b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber    int64_t getDurationUs() const;
117d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t getEstimatedTrackSizeBytes() const;
11899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    int32_t getMetaSizeIncrease(int32_t angle, int32_t trackCount) const;
119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeTrackHeader(bool use32BitOffset = true);
120230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t getMinCttsOffsetTimeUs();
1211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void bufferChunk(int64_t timestampUs);
1221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAvc() const { return mIsAvc; }
1239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool isHevc() const { return mIsHevc; }
124fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    bool isHeic() const { return mIsHeic; }
1251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isAudio() const { return mIsAudio; }
1261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool isMPEG4() const { return mIsMPEG4; }
127fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    bool usePrefix() const { return mIsAvc || mIsHevc || mIsHeic; }
12899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    bool isExifData(const MediaBufferBase *buffer) const;
129c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    void addChunkOffset(off64_t offset);
13099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    void addItemOffsetAndSize(off64_t offset, size_t size, bool isExif);
13199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    void flushItemRefs();
13270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int32_t getTrackId() const { return mTrackId; }
133dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    status_t dump(int fd, const Vector<String16>& args) const;
1348b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    static const char *getFourCCForMime(const char *mime);
13525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *getTrackType() const;
136fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    void resetInternal();
13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
139000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    enum {
14005f4cd73b9655a6d4aad9fa215d6fc13c40633aaZhijun He        kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
1418c460498c028888c533ab442be12b6d4b669b965James Dong        kSampleArraySize = 1000,
142000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    };
143000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    // A helper class to handle faster write box with table entries
145c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    template<class TYPE, unsigned ENTRY_SIZE>
146c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    // ENTRY_SIZE: # of values in each entry
147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    struct ListTableEntries {
148c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        static_assert(ENTRY_SIZE > 0, "ENTRY_SIZE must be positive");
149c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        ListTableEntries(uint32_t elementCapacity)
150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            : mElementCapacity(elementCapacity),
151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mTotalNumTableEntries(0),
152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mNumValuesInCurrEntry(0),
153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement(NULL) {
154b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_GT(mElementCapacity, 0u);
1552177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia            // Ensure no integer overflow on allocation in add().
156c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(ENTRY_SIZE, UINT32_MAX / mElementCapacity);
157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Free the allocated memory.
160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        ~ListTableEntries() {
161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (!mTableEntryList.empty()) {
162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                typename List<TYPE *>::iterator it = mTableEntryList.begin();
163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                delete[] (*it);
164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.erase(it);
165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Replace the value at the given position by the given value.
169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // There must be an existing value at the given position.
170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order
171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void set(const TYPE& value, uint32_t pos) {
173c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            CHECK_LT(pos, mTotalNumTableEntries * ENTRY_SIZE);
174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
176c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
182b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_EQ(iterations, 0u);
183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
184c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            (*it)[(pos % (mElementCapacity * ENTRY_SIZE))] = value;
185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Get the value at the given position by the given value.
188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value the retrieved value at the position in network byte order.
189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg pos location the value must be in.
190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @return true if a value is found.
191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        bool get(TYPE& value, uint32_t pos) const {
192c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if (pos >= mTotalNumTableEntries * ENTRY_SIZE) {
193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                return false;
194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            typename List<TYPE *>::iterator it = mTableEntryList.begin();
197c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE));
198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            while (it != mTableEntryList.end() && iterations > 0) {
199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++it;
200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                --iterations;
201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK(it != mTableEntryList.end());
203b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_EQ(iterations, 0u);
204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
205c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            value = (*it)[(pos % (mElementCapacity * ENTRY_SIZE))];
206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            return true;
207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
209c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // adjusts all values by |adjust(value)|
210c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        void adjustEntries(
211c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                std::function<void(size_t /* ix */, TYPE(& /* entry */)[ENTRY_SIZE])> update) {
212c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t nEntries = mTotalNumTableEntries + mNumValuesInCurrEntry / ENTRY_SIZE;
213c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            size_t ix = 0;
214c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            for (TYPE *entryArray : mTableEntryList) {
215c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                size_t num = std::min(nEntries, (size_t)mElementCapacity);
216c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                for (size_t i = 0; i < num; ++i) {
217c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    update(ix++, (TYPE(&)[ENTRY_SIZE])(*entryArray));
218c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    entryArray += ENTRY_SIZE;
219c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                }
220c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                nEntries -= num;
221c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            }
222c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        }
223c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar
224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Store a single value.
225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg value must be in network byte order.
226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void add(const TYPE& value) {
227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            CHECK_LT(mNumValuesInCurrEntry, mElementCapacity);
228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries % mElementCapacity;
229c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t nValues  = mNumValuesInCurrEntry % ENTRY_SIZE;
230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            if (nEntries == 0 && nValues == 0) {
231c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                mCurrTableEntriesElement = new TYPE[ENTRY_SIZE * mElementCapacity];
232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                CHECK(mCurrTableEntriesElement != NULL);
233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mTableEntryList.push_back(mCurrTableEntriesElement);
234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
235c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
236c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            uint32_t pos = nEntries * ENTRY_SIZE + nValues;
237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            mCurrTableEntriesElement[pos] = value;
238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            ++mNumValuesInCurrEntry;
240c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar            if ((mNumValuesInCurrEntry % ENTRY_SIZE) == 0) {
241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                ++mTotalNumTableEntries;
242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                mNumValuesInCurrEntry = 0;
243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Write out the table entries:
247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 1. the number of entries goes first
248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // 2. followed by the values in the table enties in order
249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // @arg writer the writer to actual write to the storage
250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        void write(MPEG4Writer *writer) const {
251b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross            CHECK_EQ(mNumValuesInCurrEntry % ENTRY_SIZE, 0u);
252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            uint32_t nEntries = mTotalNumTableEntries;
253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            writer->writeInt32(nEntries);
254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            for (typename List<TYPE *>::iterator it = mTableEntryList.begin();
255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                it != mTableEntryList.end(); ++it) {
256b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross                CHECK_GT(nEntries, 0u);
257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                if (nEntries >= mElementCapacity) {
258c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, mElementCapacity);
259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    nEntries -= mElementCapacity;
260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                } else {
261c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar                    writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, nEntries);
262c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    break;
263c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                }
264c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong            }
265c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        }
266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
267c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        // Return the number of entries in the table.
268c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t count() const { return mTotalNumTableEntries; }
269c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
270c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    private:
271c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mElementCapacity;  // # entries in an element
272c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t         mTotalNumTableEntries;
273c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t         mNumValuesInCurrEntry;  // up to ENTRY_SIZE
274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        TYPE             *mCurrTableEntriesElement;
275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mutable List<TYPE *>     mTableEntryList;
276c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
277c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries);
278c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    };
279c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
280c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
281c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Writer *mOwner;
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mMeta;
284ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kang    sp<MediaSource> mSource;
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    volatile bool mDone;
286a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mPaused;
287a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    volatile bool mResumed;
288eaae38445a340c4857c1c5569475879a728e63b7James Dong    volatile bool mStarted;
2891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAvc;
2909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    bool mIsHevc;
2911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsAudio;
29225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    bool mIsVideo;
293fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    bool mIsHeic;
2941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    bool mIsMPEG4;
295fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    bool mGotStartKeyFrame;
2969db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    bool mIsMalformed;
297bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t mTrackId;
298c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    int64_t mTrackDurationUs;
29943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int64_t mMaxChunkDurationUs;
300826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    int64_t mLastDecodingTimeUs;
301e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
302d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    int64_t mEstimatedTrackSizeBytes;
3031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    int64_t mMdatSizeBytes;
3048f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int32_t mTimeScale;
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_t mThread;
30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
308be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
30913aec890216948b0c364f8f92792129d0335f506James Dong    List<MediaBuffer *> mChunkSamples;
3101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
311c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    bool                mSamplesHaveSameSize;
312c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStszTableEntries;
313be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
314c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStcoTableEntries;
315c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<off64_t, 1> *mCo64TableEntries;
316c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 3> *mStscTableEntries;
317c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 1> *mStssTableEntries;
318c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mSttsTableEntries;
319c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    ListTableEntries<uint32_t, 2> *mCttsTableEntries;
320965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
321000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t mMinCttsOffsetTimeUs;
322230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t mMinCttsOffsetTicks;
323230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t mMaxCttsOffsetTicks;
324965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
325dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    // Save the last 10 frames' timestamp and frame type for debug.
326dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    struct TimestampDebugHelperEntry {
327dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        int64_t pts;
328dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        int64_t dts;
329dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        std::string frameType;
330dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    };
331dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang
332dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    std::list<TimestampDebugHelperEntry> mTimestampDebugHelper;
33362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
3343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Sequence parameter set or picture parameter set
3353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    struct AVCParamSet {
3363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        AVCParamSet(uint16_t length, const uint8_t *data)
3373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            : mLength(length), mData(data) {}
3383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t mLength;
3403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *mData;
3413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    };
3423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mSeqParamSets;
3433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    List<AVCParamSet> mPicParamSets;
3443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileIdc;
3453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mProfileCompatible;
3463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t mLevelIdc;
3473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *mCodecSpecificData;
34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t mCodecSpecificDataSize;
350548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber    bool mGotAllCodecSpecificData;
35193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    bool mTrackingProgressStatus;
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool mReachedEOS;
3543c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    int64_t mStartTimestampUs;
35570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mStartTimeRealUs;
35670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    int64_t mFirstSampleTimeRealUs;
35793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mPreviousTrackTimeUs;
35893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t mTrackEveryTimeDurationUs;
35925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
360fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int32_t mRotation;
361fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
362fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    Vector<uint16_t> mProperties;
36399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    ItemRefs mDimgRefs;
36499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    ItemRefs mCdscRefs;
36599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    uint16_t mImageItemId;
366fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int32_t mIsPrimary;
367fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int32_t mWidth, mHeight;
36867d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang    int32_t mTileWidth, mTileHeight;
369fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int32_t mGridRows, mGridCols;
370fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    size_t mNumTiles, mTileIndex;
371fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
372872a481558350634a3fd5cb67939de288af00ecbJames Dong    // Update the audio track's drift information.
373872a481558350634a3fd5cb67939de288af00ecbJames Dong    void updateDriftTime(const sp<MetaData>& meta);
374872a481558350634a3fd5cb67939de288af00ecbJames Dong
37562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    void dumpTimeStamps();
37662a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
377230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t getStartTimeOffsetTimeUs() const;
378000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int32_t getStartTimeOffsetScaledTime() const;
379000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static void *ThreadWrapper(void *me);
38137187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t threadEntry();
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *parseParamSet(
3843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen);
3853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
3869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0);
3879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
391215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong
3929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size);
3939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size);
3949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t parseHEVCCodecSpecificData(
3959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            const uint8_t *data, size_t size, HevcParameterSets &paramSets);
3969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
397215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    // Track authoring progress status
398faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    void trackProgressStatus(int64_t timeUs, status_t err = OK);
39993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    void initTrackingProgressStatus(MetaData *params);
40003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
40119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    void getCodecSpecificDataFromInputFormatIfPossible();
40219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
403c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Determine the track time scale
404c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If it is an audio track, try to use the sampling rate as
405c059860c73678a202bfa33062723e8f82fb779d9James Dong    // the time scale; however, if user chooses the overwrite
406c059860c73678a202bfa33062723e8f82fb779d9James Dong    // value, the user-supplied time scale will be used.
407c059860c73678a202bfa33062723e8f82fb779d9James Dong    void setTimeScale();
408c059860c73678a202bfa33062723e8f82fb779d9James Dong
409690f546b0ee548dbfe997df36418e5302ec2d786James Dong    // Simple validation on the codec specific data
410690f546b0ee548dbfe997df36418e5302ec2d786James Dong    status_t checkCodecSpecificData() const;
411690f546b0ee548dbfe997df36418e5302ec2d786James Dong
4121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void updateTrackSizeEstimate();
4131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStscTableEntry(size_t chunkId, size_t sampleId);
4141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    void addOneStssTableEntry(size_t sampleId);
41579761ab096f57c3027fad9556c2bc436672d614eJames Dong
41679761ab096f57c3027fad9556c2bc436672d614eJames Dong    // Duration is time scale based
41779761ab096f57c3027fad9556c2bc436672d614eJames Dong    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
418965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
41945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
42045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    bool isTrackMalFormed() const;
42143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    void sendTrackSummary(bool hasMultipleTracks);
4221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Write the boxes
424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStcoBox(bool use32BitOffset);
425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStscBox();
426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStszBox();
427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStssBox();
428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSttsBox();
429965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    void writeCttsBox();
430b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeD263Box();
431b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writePaspBox();
432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAvccBox();
4339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    void writeHvccBox();
434b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeUrlBox();
435b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDrefBox();
436b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDinfBox();
437b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeDamrBox();
438efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeMdhdBox(uint32_t now);
439b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeSmhdBox();
440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVmhdBox();
44125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    void writeNmhdBox();
442b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeHdlrBox();
443efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    void writeTkhdBox(uint32_t now);
44458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    void writeColrBox();
445b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4aEsdsBox();
446b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeMp4vEsdsBox();
447b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeAudioFourCCBox();
448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeVideoFourCCBox();
44925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    void writeMetadataFourCCBox();
450b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    void writeStblBox(bool use32BitOffset);
451b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track(const Track &);
45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track &operator=(const Track &);
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
456fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu KuangMPEG4Writer::MPEG4Writer(int fd) {
4575ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    initInternal(fd, true /*isFirstSession*/);
45830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
45930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() {
4618bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong    reset();
46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    while (!mTracks.empty()) {
4641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        List<Track *>::iterator it = mTracks.begin();
46520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete *it;
4661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        (*it) = NULL;
4671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mTracks.erase(it);
46820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.clear();
470fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
471fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd != -1) {
472fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        close(mNextFd);
473fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
474fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
475fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
4765ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuangvoid MPEG4Writer::initInternal(int fd, bool isFirstSession) {
477fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("initInternal");
4788fdb3fde346b446ad3b04dafa65a6844da672e23Hangyu Kuang    mFd = dup(fd);
479fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mNextFd = -1;
480fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mInitCheck = mFd < 0? NO_INIT: OK;
4815ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
4825ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mInterleaveDurationUs = 1000000;
4835ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
4845ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mStartTimestampUs = -1ll;
4855ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mStartTimeOffsetMs = -1;
486fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mPaused = false;
487fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStarted = false;
488fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mWriterThreadStarted = false;
489fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSendNotify = false;
4905ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
4915ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    // Reset following variables for all the sessions and they will be
4925ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    // initialized in start(MetaData *param).
4935ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mIsRealTimeRecording = true;
4945ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mUse4ByteNalLength = true;
4955ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    mUse32BitOffset = true;
496fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mOffset = 0;
497fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mMdatOffset = 0;
498720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCache = NULL;
499720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCacheOffset = 0;
500720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCacheSize = 0;
501720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mWriteBoxToMemory = false;
502fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mFreeBoxOffset = 0;
503fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStreamableFile = false;
504fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mTimeScale = -1;
505fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mHasFileLevelMeta = false;
506fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mPrimaryItemId = 0;
507fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mAssociationEntryCount = 0;
508fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mNumGrids = 0;
50999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    mHasRefs = false;
5105ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
5115ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    // Following variables only need to be set for the first recording session.
5125ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    // And they will stay the same for all the recording sessions.
5135ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    if (isFirstSession) {
5145ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mMoovExtraSize = 0;
5152504ce46a75c86bb1f8ed6f839dd30e2ec7b400aHangyu Kuang        mHasMoovBox = false;
5165ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mMetaKeys = new AMessage();
5175ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        addDeviceMeta();
5185ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mLatitudex10000 = 0;
5195ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mLongitudex10000 = 0;
5205ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mAreGeoTagsAvailable = false;
5215ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mSwitchPending = false;
5225ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang        mIsFileSizeLimitExplicitlyRequested = false;
5235ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    }
5245ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang
525fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // Verify mFd is seekable
526fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    off64_t off = lseek64(mFd, 0, SEEK_SET);
527fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (off < 0) {
528fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGE("cannot seek mFd: %s (%d) %lld", strerror(errno), errno, (long long)mFd);
529fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        release();
530fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
531fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
532fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         it != mTracks.end(); ++it) {
533fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        (*it)->resetInternal();
534fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
537dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump(
538dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        int fd, const Vector<String16>& args) {
539dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
540dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
541dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
542dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
543dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
544dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
545dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
546dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
547dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    for (List<Track *>::iterator it = mTracks.begin();
548dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong         it != mTracks.end(); ++it) {
549dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong        (*it)->dump(fd, args);
550dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    }
551dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
552dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
553dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
554dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump(
55584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int fd, const Vector<String16>& /* args */) const {
556dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    const size_t SIZE = 256;
557dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    char buffer[SIZE];
558dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    String8 result;
55925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    snprintf(buffer, SIZE, "     %s track\n", getTrackType());
560dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
561dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    snprintf(buffer, SIZE, "       reached EOS: %s\n",
562dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong            mReachedEOS? "true": "false");
563dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    result.append(buffer);
564c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    snprintf(buffer, SIZE, "       frames encoded : %d\n", mStszTableEntries->count());
56513210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
566377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
56713210f3346462a86ce9fe3af72a0c200dba84e27James Dong    result.append(buffer);
568dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    ::write(fd, result.string(), result.size());
569dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong    return OK;
570dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong}
571dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong
5728b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static
5738b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
5748b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (mime == NULL) {
5758b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        return NULL;
5768b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
5778b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (!strncasecmp(mime, "audio/", 6)) {
5788b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
5798b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "samr";
5808b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
5818b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "sawb";
5828b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
5838b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4a";
5848b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
5858b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else if (!strncasecmp(mime, "video/", 6)) {
5868b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
5878b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "mp4v";
5888b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
5898b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "s263";
5908b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
5918b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan            return "avc1";
5929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
5939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return "hvc1";
5948b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan        }
59525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (!strncasecmp(mime, "application/", 12)) {
59625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        return "mett";
597fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    } else if (!strcasecmp(MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, mime)) {
598fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        return "heic";
5998b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    } else {
60025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Track (%s) other than video/audio/metadata is not supported", mime);
6018b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    }
6028b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    return NULL;
6038b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan}
6048b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan
605ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kangstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
606bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    Mutex::Autolock l(mLock);
607bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    if (mStarted) {
60829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Attempt to add source AFTER recording is started");
609bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        return UNKNOWN_ERROR;
610bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    }
611acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
612acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    CHECK(source.get() != NULL);
613acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
614acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    const char *mime;
615acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    source->getFormat()->findCString(kKeyMIMEType, &mime);
616acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
61725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (Track::getFourCCForMime(mime) == NULL) {
61825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Unsupported mime '%s'", mime);
61925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        return ERROR_UNSUPPORTED;
62025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
62125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
62225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    // This is a metadata track or the first track of either audio or video
623acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    // Go ahead to add the track.
624219f195159f93d627af2b243732e3f9020511a46James Dong    Track *track = new Track(this, source, 1 + mTracks.size());
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTracks.push_back(track);
6262dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber
627fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mHasMoovBox |= !track->isHeic();
628fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mHasFileLevelMeta |= track->isHeic();
629fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
6302dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber    return OK;
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) {
634acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    if (mTracks.empty()) {
635acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        ALOGE("No source added");
636acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong        return INVALID_OPERATION;
637acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong    }
638acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong
639a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    for (List<Track *>::iterator it = mTracks.begin();
640a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong         it != mTracks.end(); ++it) {
64193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        status_t err = (*it)->start(params);
642a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
643a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (err != OK) {
644a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            for (List<Track *>::iterator it2 = mTracks.begin();
645a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                 it2 != it; ++it2) {
646a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong                (*it2)->stop();
647a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            }
648a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
649a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            return err;
650a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
651a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
652a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    return OK;
653a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
654a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
6557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() {
6567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // add device info and estimate space in 'moov'
6577c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    char val[PROPERTY_VALUE_MAX];
6587c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size_t n;
6597c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // meta size is estimated by adding up the following:
6607c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - meta header structures, which occur only once (total 66 bytes)
6617c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // - size for each key, which consists of a fixed header (32 bytes),
6627c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    //   plus key length and data length.
6637c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 66;
6647c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.version.release", val, NULL)
6657c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6667c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
6677c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
6687c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
669da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang
670da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang    if (property_get_bool("media.recorder.show_manufacturer_and_model", false)) {
671da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        if (property_get("ro.product.manufacturer", val, NULL)
672da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang                && (n = strlen(val)) > 0) {
673da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMetaKeys->setString(kMetaKey_Manufacturer, val, n + 1);
674da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMoovExtraSize += sizeof(kMetaKey_Manufacturer) + n + 32;
675da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        }
676da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        if (property_get("ro.product.model", val, NULL)
677da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang                && (n = strlen(val)) > 0) {
678da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMetaKeys->setString(kMetaKey_Model, val, n + 1);
679da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang            mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
680da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang        }
6817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
682da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang#ifdef SHOW_MODEL_BUILD
6837c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    if (property_get("ro.build.display.id", val, NULL)
6847c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            && (n = strlen(val)) > 0) {
6857c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
6867c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
6877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    }
6887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif
6897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang}
6907c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
69199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhangint64_t MPEG4Writer::estimateFileLevelMetaSize(MetaData *params) {
69299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    int32_t rotation;
69399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    if (!params || !params->findInt32(kKeyRotation, &rotation)) {
69499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        rotation = 0;
69599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    }
69699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
697fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // base meta size
698fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int64_t metaSize =     12  // meta fullbox header
699fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 33  // hdlr box
700fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 14  // pitm box
701fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 16  // iloc box (fixed size portion)
702fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 14  // iinf box (fixed size portion)
703fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 32  // iprp box (fixed size protion)
704fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 8   // idat box (when empty)
705fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         + 12  // iref box (when empty)
706fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                         ;
707fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
708fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (List<Track *>::iterator it = mTracks.begin();
709fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang         it != mTracks.end(); ++it) {
710fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if ((*it)->isHeic()) {
71199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            metaSize += (*it)->getMetaSizeIncrease(rotation, mTracks.size());
712fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
713fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
714fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
715fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    ALOGV("estimated meta size: %lld", (long long) metaSize);
716fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
717fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // Need at least 8-byte padding at the end, otherwise the left-over
718fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // freebox may become malformed
719fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    return metaSize + 8;
720fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
721fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
7222dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
7232dec2b5be2056c6d9428897dc672185872d30d17James Dong    // This implementation is highly experimental/heurisitic.
7242dec2b5be2056c6d9428897dc672185872d30d17James Dong    //
7252dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Statistical analysis shows that metadata usually accounts
7262dec2b5be2056c6d9428897dc672185872d30d17James Dong    // for a small portion of the total file size, usually < 0.6%.
7272dec2b5be2056c6d9428897dc672185872d30d17James Dong
72878a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
7292dec2b5be2056c6d9428897dc672185872d30d17James Dong    // where 1MB is the common file size limit for MMS application.
73078a1a286f736888ae7af8860b2c424af0d978848James Dong    // The default MAX _MOOV_BOX_SIZE value is based on about 3
7312dec2b5be2056c6d9428897dc672185872d30d17James Dong    // minute video recording with a bit rate about 3 Mbps, because
7322dec2b5be2056c6d9428897dc672185872d30d17James Dong    // statistics also show that most of the video captured are going
7332dec2b5be2056c6d9428897dc672185872d30d17James Dong    // to be less than 3 minutes.
7342dec2b5be2056c6d9428897dc672185872d30d17James Dong
7352dec2b5be2056c6d9428897dc672185872d30d17James Dong    // If the estimation is wrong, we will pay the price of wasting
7362dec2b5be2056c6d9428897dc672185872d30d17James Dong    // some reserved space. This should not happen so often statistically.
7372dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int32_t factor = mUse32BitOffset? 1: 2;
73878a1a286f736888ae7af8860b2c424af0d978848James Dong    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
7392dec2b5be2056c6d9428897dc672185872d30d17James Dong    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
7402dec2b5be2056c6d9428897dc672185872d30d17James Dong    int64_t size = MIN_MOOV_BOX_SIZE;
7412dec2b5be2056c6d9428897dc672185872d30d17James Dong
74278a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file size limit is set
743a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
74478a1a286f736888ae7af8860b2c424af0d978848James Dong        size = mMaxFileSizeLimitBytes * 6 / 1000;
74578a1a286f736888ae7af8860b2c424af0d978848James Dong    }
74678a1a286f736888ae7af8860b2c424af0d978848James Dong
74778a1a286f736888ae7af8860b2c424af0d978848James Dong    // Max file duration limit is set
74878a1a286f736888ae7af8860b2c424af0d978848James Dong    if (mMaxFileDurationLimitUs != 0) {
74978a1a286f736888ae7af8860b2c424af0d978848James Dong        if (bitRate > 0) {
75078a1a286f736888ae7af8860b2c424af0d978848James Dong            int64_t size2 =
7510ca31521644b9396829850f7400d23f9b107cc64Johan Redestig                ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000;
75278a1a286f736888ae7af8860b2c424af0d978848James Dong            if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
75378a1a286f736888ae7af8860b2c424af0d978848James Dong                // When both file size and duration limits are set,
75478a1a286f736888ae7af8860b2c424af0d978848James Dong                // we use the smaller limit of the two.
75578a1a286f736888ae7af8860b2c424af0d978848James Dong                if (size > size2) {
75678a1a286f736888ae7af8860b2c424af0d978848James Dong                    size = size2;
75778a1a286f736888ae7af8860b2c424af0d978848James Dong                }
75878a1a286f736888ae7af8860b2c424af0d978848James Dong            } else {
75978a1a286f736888ae7af8860b2c424af0d978848James Dong                // Only max file duration limit is set
76078a1a286f736888ae7af8860b2c424af0d978848James Dong                size = size2;
76178a1a286f736888ae7af8860b2c424af0d978848James Dong            }
7622dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
7632dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
76478a1a286f736888ae7af8860b2c424af0d978848James Dong
7652dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size < MIN_MOOV_BOX_SIZE) {
7662dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MIN_MOOV_BOX_SIZE;
7672dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7682dec2b5be2056c6d9428897dc672185872d30d17James Dong
7692dec2b5be2056c6d9428897dc672185872d30d17James Dong    // Any long duration recording will be probably end up with
7702dec2b5be2056c6d9428897dc672185872d30d17James Dong    // non-streamable mp4 file.
7712dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (size > MAX_MOOV_BOX_SIZE) {
7722dec2b5be2056c6d9428897dc672185872d30d17James Dong        size = MAX_MOOV_BOX_SIZE;
7732dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
7742dec2b5be2056c6d9428897dc672185872d30d17James Dong
7757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    // Account for the extra stuff (Geo, meta keys, etc.)
7767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    size += mMoovExtraSize;
7777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
778a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
779a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn         " estimated moov size %" PRId64 " bytes",
7802dec2b5be2056c6d9428897dc672185872d30d17James Dong         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
781fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
782fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int64_t estimatedSize = factor * size;
783fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    CHECK_GE(estimatedSize, 8);
784fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
785fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    return estimatedSize;
7862dec2b5be2056c6d9428897dc672185872d30d17James Dong}
7872dec2b5be2056c6d9428897dc672185872d30d17James Dong
7882dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) {
789674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
79025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return UNKNOWN_ERROR;
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
792fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mStartMeta = param;
79320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
794a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    /*
795a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * Check mMaxFileSizeLimitBytes at the beginning
796a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * since mMaxFileSizeLimitBytes may be implicitly
797a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * changed later for 32-bit file offset even if
798a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     * user does not ask to set it explicitly.
799a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong     */
800a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    if (mMaxFileSizeLimitBytes != 0) {
801a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong        mIsFileSizeLimitExplicitlyRequested = true;
802a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong    }
803a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong
8042dec2b5be2056c6d9428897dc672185872d30d17James Dong    int32_t use64BitOffset;
8052dec2b5be2056c6d9428897dc672185872d30d17James Dong    if (param &&
8062dec2b5be2056c6d9428897dc672185872d30d17James Dong        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
8072dec2b5be2056c6d9428897dc672185872d30d17James Dong        use64BitOffset) {
8082dec2b5be2056c6d9428897dc672185872d30d17James Dong        mUse32BitOffset = false;
8092dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
8102dec2b5be2056c6d9428897dc672185872d30d17James Dong
8111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    if (mUse32BitOffset) {
8121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // Implicit 32 bit file size limit
8131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes == 0) {
8141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
8151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
8161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
8171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // If file size is set to be larger than the 32 bit file
8181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        // size limit, treat it as an error.
8191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
820a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
821a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                 "It is changed to %" PRId64 " bytes",
822d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong                mMaxFileSizeLimitBytes, kMax32BitFileSize);
823d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong            mMaxFileSizeLimitBytes = kMax32BitFileSize;
8241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        }
8251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    }
8261f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
827b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    int32_t use2ByteNalLength;
828b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (param &&
829b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
830b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        use2ByteNalLength) {
831b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mUse4ByteNalLength = false;
8322dec2b5be2056c6d9428897dc672185872d30d17James Dong    }
8332dec2b5be2056c6d9428897dc672185872d30d17James Dong
834de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    int32_t isRealTimeRecording;
835de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
836de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        mIsRealTimeRecording = isRealTimeRecording;
837de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
838de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
839065d1aff96818df54456053f1574aec8a234d0deJames Dong    mStartTimestampUs = -1;
84093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
841a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (mStarted) {
842a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused) {
843a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            mPaused = false;
84493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            return startTracks(param);
845a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
846a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
847a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
848a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
8498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    if (!param ||
8508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
8518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        mTimeScale = 1000;
8528f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    }
85343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
8543856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("movie time scale: %d", mTimeScale);
8558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
85677e8ae9967a078770416619e99ddb5b010def312James Dong    /*
85777e8ae9967a078770416619e99ddb5b010def312James Dong     * When the requested file size limit is small, the priority
85877e8ae9967a078770416619e99ddb5b010def312James Dong     * is to meet the file size limit requirement, rather than
8597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to make the file streamable. mStreamableFile does not tell
8607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * whether the actual recorded file is streamable or not.
86177e8ae9967a078770416619e99ddb5b010def312James Dong     */
86277e8ae9967a078770416619e99ddb5b010def312James Dong    mStreamableFile =
86377e8ae9967a078770416619e99ddb5b010def312James Dong        (mMaxFileSizeLimitBytes != 0 &&
86477e8ae9967a078770416619e99ddb5b010def312James Dong         mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes);
86577e8ae9967a078770416619e99ddb5b010def312James Dong
8667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    /*
867720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * mWriteBoxToMemory is true if the amount of data in a file-level meta or
868720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * moov box is smaller than the reserved free space at the beginning of a
869720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * file, AND when the content of the box is constructed. Note that video/
870720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * audio frame data is always written to the file but not in the memory.
8717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
872720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * Before stop()/reset() is called, mWriteBoxToMemory is always
8737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * false. When reset() is called at the end of a recording session,
874720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * file-level meta and/or moov box needs to be constructed.
8757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
876720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * 1) Right before the box is constructed, mWriteBoxToMemory to set to
877720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * mStreamableFile so that if the file is intended to be streamable, it
878720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * is set to true; otherwise, it is set to false. When the value is set
879720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * to false, all the content of that box is written immediately to
8807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * the end of the file. When the value is set to true, all the
881720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * content of that box is written to an in-memory cache,
882720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * mInMemoryCache, util the following condition happens. Note
8837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * that the size of the in-memory cache is the same as the
8847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * reserved free space at the beginning of the file.
8857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
886720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * 2) While the data of the box is written to an in-memory
8877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * cache, the data size is checked against the reserved space.
888720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * If the data size surpasses the reserved space, subsequent box data
889720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * could no longer be hold in the in-memory cache. This also
8907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * indicates that the reserved space was too small. At this point,
891720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * _all_ subsequent box data must be written to the end of the file.
892720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * mWriteBoxToMemory must be set to false to direct the write
8937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     * to the file.
8947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     *
895720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * 3) If the data size in the box is smaller than the reserved
896720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * space after the box is completely constructed, the in-memory
897720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * cache copy of the box is written to the reserved free space.
898720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * mWriteBoxToMemory is always set to false after all boxes that
899720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang     * using the in-memory cache have been constructed.
9007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong     */
901720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mWriteBoxToMemory = false;
902720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCache = NULL;
903720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCacheOffset = 0;
9047837c17063a4c50bc856ba59418516fdab731de7James Dong
905fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
906fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    ALOGV("muxer starting: mHasMoovBox %d, mHasFileLevelMeta %d",
907fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mHasMoovBox, mHasFileLevelMeta);
908fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeFtypBox(param);
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9117837c17063a4c50bc856ba59418516fdab731de7James Dong    mFreeBoxOffset = mOffset;
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
913720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    if (mInMemoryCacheSize == 0) {
9142dec2b5be2056c6d9428897dc672185872d30d17James Dong        int32_t bitRate = -1;
915fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mHasFileLevelMeta) {
91699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            mInMemoryCacheSize += estimateFileLevelMetaSize(param);
917fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
918fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mHasMoovBox) {
919fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (param) {
920fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                param->findInt32(kKeyBitRate, &bitRate);
921fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
922720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mInMemoryCacheSize += estimateMoovBoxSize(bitRate);
9232dec2b5be2056c6d9428897dc672185872d30d17James Dong        }
9247837c17063a4c50bc856ba59418516fdab731de7James Dong    }
92577e8ae9967a078770416619e99ddb5b010def312James Dong    if (mStreamableFile) {
92677e8ae9967a078770416619e99ddb5b010def312James Dong        // Reserve a 'free' box only for streamable file
92777e8ae9967a078770416619e99ddb5b010def312James Dong        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
928720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        writeInt32(mInMemoryCacheSize);
92977e8ae9967a078770416619e99ddb5b010def312James Dong        write("free", 4);
930720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        mMdatOffset = mFreeBoxOffset + mInMemoryCacheSize;
93177e8ae9967a078770416619e99ddb5b010def312James Dong    } else {
93277e8ae9967a078770416619e99ddb5b010def312James Dong        mMdatOffset = mOffset;
93377e8ae9967a078770416619e99ddb5b010def312James Dong    }
9347837c17063a4c50bc856ba59418516fdab731de7James Dong
9357837c17063a4c50bc856ba59418516fdab731de7James Dong    mOffset = mMdatOffset;
936c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mMdatOffset, SEEK_SET);
9371acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
9381acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("????mdat", 8);
9391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
9401acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        write("\x00\x00\x00\x01mdat????????", 16);
9411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
9421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    status_t err = startWriterThread();
9441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (err != OK) {
9451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        return err;
9461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    err = startTracks(param);
949a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (err != OK) {
950a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return err;
95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
9521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
953a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mStarted = true;
95425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const {
9581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    return mUse32BitOffset;
9591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
9601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
96137187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() {
9625ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    ALOGW("MPEG4Writer: pause is not supported");
9635ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang    return ERROR_UNSUPPORTED;
964a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
965a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
9661c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() {
967b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Stopping writer thread");
968411ba422e3635d534928ffd81abf54f4f291c739James Dong    if (!mWriterThreadStarted) {
969411ba422e3635d534928ffd81abf54f4f291c739James Dong        return;
970411ba422e3635d534928ffd81abf54f4f291c739James Dong    }
9711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    {
9731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        Mutex::Autolock autolock(mLock);
9741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mDone = true;
9761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkReadyCondition.signal();
9771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
9781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
9791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    void *dummy;
9801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_join(mThread, &dummy);
981411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = false;
982b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("Writer thread stopped");
9831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
9841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
98513f6284305e4b27395a23db7882d670bdb1bcae1James Dong/*
98613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix:
98713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a  b  u |
98813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c  d  v |
98913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x  y  w |
99013f6284305e4b27395a23db7882d670bdb1bcae1James Dong *
99113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following
99213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w},
99313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while
99413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format.
99513f6284305e4b27395a23db7882d670bdb1bcae1James Dong */
99613f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) {
9973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeCompositionMatrix");
99813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t a = 0x00010000;
99913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t b = 0;
100013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t c = 0;
100113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    uint32_t d = 0x00010000;
100213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    switch (degrees) {
100313f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 0:
100413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
100513f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 90:
100613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
100713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0x00010000;
100813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0xFFFF0000;
100913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
101013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
101113f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 180:
101213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0xFFFF0000;
101313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0xFFFF0000;
101413f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
101513f6284305e4b27395a23db7882d670bdb1bcae1James Dong        case 270:
101613f6284305e4b27395a23db7882d670bdb1bcae1James Dong            a = 0;
101713f6284305e4b27395a23db7882d670bdb1bcae1James Dong            b = 0xFFFF0000;
101813f6284305e4b27395a23db7882d670bdb1bcae1James Dong            c = 0x00010000;
101913f6284305e4b27395a23db7882d670bdb1bcae1James Dong            d = 0;
102013f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
102113f6284305e4b27395a23db7882d670bdb1bcae1James Dong        default:
102213f6284305e4b27395a23db7882d670bdb1bcae1James Dong            CHECK(!"Should never reach this unknown rotation");
102313f6284305e4b27395a23db7882d670bdb1bcae1James Dong            break;
102413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
102513f6284305e4b27395a23db7882d670bdb1bcae1James Dong
102613f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(a);           // a
102713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(b);           // b
102813f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // u
102913f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(c);           // c
103013f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(d);           // d
103113f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // v
103213f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // x
103313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0);           // y
103413f6284305e4b27395a23db7882d670bdb1bcae1James Dong    writeInt32(0x40000000);  // w
103513f6284305e4b27395a23db7882d670bdb1bcae1James Dong}
103613f6284305e4b27395a23db7882d670bdb1bcae1James Dong
1037411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() {
1038411ba422e3635d534928ffd81abf54f4f291c739James Dong    close(mFd);
1039411ba422e3635d534928ffd81abf54f4f291c739James Dong    mFd = -1;
1040411ba422e3635d534928ffd81abf54f4f291c739James Dong    mInitCheck = NO_INIT;
1041411ba422e3635d534928ffd81abf54f4f291c739James Dong    mStarted = false;
1042720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    free(mInMemoryCache);
1043720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCache = NULL;
1044411ba422e3635d534928ffd81abf54f4f291c739James Dong}
104513f6284305e4b27395a23db7882d670bdb1bcae1James Dong
1046fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::finishCurrentSession() {
1047fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    reset(false /* stopSource */);
1048fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1049fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1050fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::switchFd() {
1051fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("switchFd");
1052fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock l(mLock);
1053fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mSwitchPending) {
1054fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return OK;
1055fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1056fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1057fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd == -1) {
1058fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGW("No FileDescripter for next recording");
1059fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return INVALID_OPERATION;
1060fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1061fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1062fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSwitchPending = true;
1063fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    sp<AMessage> msg = new AMessage(kWhatSwitch, mReflector);
1064fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    status_t err = msg->post();
1065fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1066fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return err;
1067fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1068fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1069fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::reset(bool stopSource) {
1070674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mInitCheck != OK) {
107137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
1072411ba422e3635d534928ffd81abf54f4f291c739James Dong    } else {
1073411ba422e3635d534928ffd81abf54f4f291c739James Dong        if (!mWriterThreadStarted ||
1074411ba422e3635d534928ffd81abf54f4f291c739James Dong            !mStarted) {
1075411ba422e3635d534928ffd81abf54f4f291c739James Dong            if (mWriterThreadStarted) {
1076411ba422e3635d534928ffd81abf54f4f291c739James Dong                stopWriterThread();
1077411ba422e3635d534928ffd81abf54f4f291c739James Dong            }
1078411ba422e3635d534928ffd81abf54f4f291c739James Dong            release();
1079411ba422e3635d534928ffd81abf54f4f291c739James Dong            return OK;
1080411ba422e3635d534928ffd81abf54f4f291c739James Dong        }
108120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
108220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
108337187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = OK;
10848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t maxDurationUs = 0;
108565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    int64_t minDurationUs = 0x7fffffffffffffffLL;
1086fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    int32_t nonImageTrackCount = 0;
108720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
1088fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        it != mTracks.end(); ++it) {
1089fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        status_t status = (*it)->stop(stopSource);
109037187916a486504acaf83bea30147eb5fbf46ae5James Dong        if (err == OK && status != OK) {
109137187916a486504acaf83bea30147eb5fbf46ae5James Dong            err = status;
109237187916a486504acaf83bea30147eb5fbf46ae5James Dong        }
109320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1094fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // skip image tracks
1095fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if ((*it)->isHeic()) continue;
1096fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        nonImageTrackCount++;
1097fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
10988f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        int64_t durationUs = (*it)->getDurationUs();
10998f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong        if (durationUs > maxDurationUs) {
11008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong            maxDurationUs = durationUs;
110120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
110265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        if (durationUs < minDurationUs) {
110365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs = durationUs;
110465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong        }
110565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong    }
110665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong
1107fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (nonImageTrackCount > 1) {
1108a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us",
110965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong            minDurationUs, maxDurationUs);
111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    stopWriterThread();
11137837c17063a4c50bc856ba59418516fdab731de7James Dong
111437187916a486504acaf83bea30147eb5fbf46ae5James Dong    // Do not write out movie header on error.
111537187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err != OK) {
1116411ba422e3635d534928ffd81abf54f4f291c739James Dong        release();
111737187916a486504acaf83bea30147eb5fbf46ae5James Dong        return err;
111837187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
111937187916a486504acaf83bea30147eb5fbf46ae5James Dong
112020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Fix up the size of the 'mdat' chunk.
11211acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    if (mUse32BitOffset) {
1122c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset, SEEK_SET);
11231f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
1124c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 4);
11251acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    } else {
1126c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
11271f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad        uint64_t size = mOffset - mMdatOffset;
11281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong        size = hton64(size);
1129c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &size, 8);
11301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong    }
1131c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(mFd, mOffset, SEEK_SET);
113220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1133720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    // Construct file-level meta and moov box now
1134720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCacheOffset = 0;
1135720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mWriteBoxToMemory = mStreamableFile;
1136720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    if (mWriteBoxToMemory) {
11377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong        // There is no need to allocate in-memory cache
1138720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        // if the file is not streamable.
11397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1140720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        mInMemoryCache = (uint8_t *) malloc(mInMemoryCacheSize);
1141720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        CHECK(mInMemoryCache != NULL);
11427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
11437837c17063a4c50bc856ba59418516fdab731de7James Dong
1144fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mHasFileLevelMeta) {
1145fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeFileLevelMetaBox();
1146720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        if (mWriteBoxToMemory) {
1147fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeCachedBoxToFile("meta");
1148fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else {
1149fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            ALOGI("The file meta box is written at the end.");
1150fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1151fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
11527837c17063a4c50bc856ba59418516fdab731de7James Dong
1153fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mHasMoovBox) {
1154fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeMoovBox(maxDurationUs);
1155720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        // mWriteBoxToMemory could be set to false in
1156fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // MPEG4Writer::write() method
1157720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        if (mWriteBoxToMemory) {
1158fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeCachedBoxToFile("moov");
1159fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else {
1160fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            ALOGI("The mp4 file will not be streamable.");
1161fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
11627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong    }
1163720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mWriteBoxToMemory = false;
11647837c17063a4c50bc856ba59418516fdab731de7James Dong
1165720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    // Free in-memory cache for box writing
1166720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    if (mInMemoryCache != NULL) {
1167720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        free(mInMemoryCache);
1168720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        mInMemoryCache = NULL;
1169720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        mInMemoryCacheOffset = 0;
11707837c17063a4c50bc856ba59418516fdab731de7James Dong    }
11717837c17063a4c50bc856ba59418516fdab731de7James Dong
11720c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(mBoxes.empty());
117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1174411ba422e3635d534928ffd81abf54f4f291c739James Dong    release();
117537187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1178fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang/*
1179fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang * Writes currently cached box into file.
1180fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang *
1181720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang * Must be called while mWriteBoxToMemory is true, and will not modify
1182720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang * mWriteBoxToMemory. After the call, remaining cache size will be
1183fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang * reduced and buffer offset will be set to the beginning of the cache.
1184fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang */
1185fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeCachedBoxToFile(const char *type) {
1186720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    CHECK(mWriteBoxToMemory);
1187fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1188720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mWriteBoxToMemory = false;
1189720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    // Content of the box is saved in the cache, and the in-memory
1190720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    // box needs to be written to the file in a single shot.
1191fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1192720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    CHECK_LE(mInMemoryCacheOffset + 8, mInMemoryCacheSize);
1193fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1194fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // Cached box
1195fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    lseek64(mFd, mFreeBoxOffset, SEEK_SET);
1196fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mOffset = mFreeBoxOffset;
1197720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    write(mInMemoryCache, 1, mInMemoryCacheOffset);
1198fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1199fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // Free box
1200fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    lseek64(mFd, mOffset, SEEK_SET);
1201fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mFreeBoxOffset = mOffset;
1202720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    writeInt32(mInMemoryCacheSize - mInMemoryCacheOffset);
1203fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    write("free", 4);
1204fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1205720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    // Rewind buffering to the beginning, and restore mWriteBoxToMemory flag
1206720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCacheSize -= mInMemoryCacheOffset;
1207720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mInMemoryCacheOffset = 0;
1208720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mWriteBoxToMemory = true;
1209fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1210fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    ALOGV("dumped out %s box, estimated size remaining %lld",
1211720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            type, (long long)mInMemoryCacheSize);
1212fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
1213fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1214efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() {
1215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    time_t now = time(NULL);
1216efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // MP4 file uses time counting seconds since midnight, Jan. 1, 1904
1217efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // while time function returns Unix epoch values which starts
1218efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    // at 1970-01-01. Lets add the number of seconds between them
12192b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60);
12202b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    if (now < 0 || uint32_t(now) > UINT32_MAX - delta) {
12212b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen        return 0;
12222b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    }
12232b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen    uint32_t mpeg4Time = uint32_t(now) + delta;
1224efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    return mpeg4Time;
1225efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson}
1226efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson
1227efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) {
1228efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
1229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("mvhd");
1230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // version=0, flags=0
1231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // creation time
1232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(now);           // modification time
1233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTimeScale);    // mvhd timescale
1234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
1235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(duration);
1236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0x10000);       // rate: 1.0
1237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0x100);         // volume
1238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt16(0);             // reserved
1239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // reserved
1241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeCompositionMatrix(0); // matrix
1242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1243b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1244b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1245b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1246b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1247b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(0);             // predefined
1248b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeInt32(mTracks.size() + 1);  // nextTrackID
1249b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // mvhd
1250b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1251b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1252b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) {
1253b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("moov");
1254b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeMvhdBox(durationUs);
125507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (mAreGeoTagsAvailable) {
125607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        writeUdtaBox();
125707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
1258fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeMoovLevelMetaBox();
1259230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // Loop through all the tracks to get the global time offset if there is
1260230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // any ctts table appears in a video track.
1261230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t minCttsOffsetTimeUs = kMaxCttsOffsetTimeUs;
1262b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    for (List<Track *>::iterator it = mTracks.begin();
1263230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        it != mTracks.end(); ++it) {
1264fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!(*it)->isHeic()) {
1265fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            minCttsOffsetTimeUs =
1266fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                std::min(minCttsOffsetTimeUs, (*it)->getMinCttsOffsetTimeUs());
1267fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1268230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    }
1269230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    ALOGI("Ajust the moov start time from %lld us -> %lld us",
1270230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang            (long long)mStartTimestampUs,
1271230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang            (long long)(mStartTimestampUs + minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs));
1272230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // Adjust the global start time.
1273230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    mStartTimestampUs += minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs;
1274230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang
1275230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
1276230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        it != mTracks.end(); ++it) {
1277fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!(*it)->isHeic()) {
1278fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            (*it)->writeTrackHeader(mUse32BitOffset);
1279fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1281b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();  // moov
1282b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1283b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
12842cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) {
1285b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    beginBox("ftyp");
1286b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1287b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t fileType;
1288fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (!param || !param->findInt32(kKeyFileType, &fileType)) {
1289fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        fileType = OUTPUT_FORMAT_MPEG_4;
1290fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
1291fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (fileType != OUTPUT_FORMAT_MPEG_4 && fileType != OUTPUT_FORMAT_HEIF) {
1292b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeFourcc("3gp4");
12938284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
12948284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("isom");
12958284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeFourcc("3gp4");
1296b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
1297fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // Only write "heic" as major brand if the client specified HEIF
1298fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // AND we indeed receive some image heic tracks.
1299fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (fileType == OUTPUT_FORMAT_HEIF && mHasFileLevelMeta) {
1300fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeFourcc("heic");
1301fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else {
1302fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeFourcc("mp42");
1303fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
13048284de3be2ac07d8774b15e6565df5aba084db04Robert Shih        writeInt32(0);
1305fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mHasFileLevelMeta) {
1306fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeFourcc("mif1");
1307fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeFourcc("heic");
1308fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1309fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mHasMoovBox) {
1310fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeFourcc("isom");
1311fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeFourcc("mp42");
1312fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1313b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
1314b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
1315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    endBox();
1316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
1317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
131807ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() {
131907ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5)
132007ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5"
132107ec01904613a0bac32caaa8444b4690998faed7James Dong#endif
132207ec01904613a0bac32caaa8444b4690998faed7James Dong
132307ec01904613a0bac32caaa8444b4690998faed7James Dong    // Test mode is enabled only if rw.media.record.test system
132407ec01904613a0bac32caaa8444b4690998faed7James Dong    // property is enabled.
132596626b7f9a4e5c9e1e04f7f710383631d1470364Marco Nelissen    if (property_get_bool("rw.media.record.test", false)) {
132607ec01904613a0bac32caaa8444b4690998faed7James Dong        return true;
132707ec01904613a0bac32caaa8444b4690998faed7James Dong    }
132807ec01904613a0bac32caaa8444b4690998faed7James Dong    return false;
132907ec01904613a0bac32caaa8444b4690998faed7James Dong}
133007ec01904613a0bac32caaa8444b4690998faed7James Dong
133170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() {
133207ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send session summary only if test mode is enabled
133307ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
133407ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
133507ec01904613a0bac32caaa8444b4690998faed7James Dong    }
133607ec01904613a0bac32caaa8444b4690998faed7James Dong
133770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
133870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong         it != mChunkInfos.end(); ++it) {
133970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int trackNum = it->mTrack->getTrackId() << 28;
134070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
134170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
134270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs);
134370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    }
134470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong}
134570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
134613aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
134713aec890216948b0c364f8f92792129d0335f506James Dong    mInterleaveDurationUs = durationUs;
134813aec890216948b0c364f8f92792129d0335f506James Dong    return OK;
134913aec890216948b0c364f8f92792129d0335f506James Dong}
135013aec890216948b0c364f8f92792129d0335f506James Dong
135113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() {
135213aec890216948b0c364f8f92792129d0335f506James Dong    mLock.lock();
135313aec890216948b0c364f8f92792129d0335f506James Dong}
135413aec890216948b0c364f8f92792129d0335f506James Dong
135513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() {
135613aec890216948b0c364f8f92792129d0335f506James Dong    mLock.unlock();
135713aec890216948b0c364f8f92792129d0335f506James Dong}
135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1359fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangoff64_t MPEG4Writer::addSample_l(
136099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        MediaBuffer *buffer, bool usePrefix, bool isExif, size_t *bytesWritten) {
1361c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t old_offset = mOffset;
136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1363fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (usePrefix) {
1364fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        addMultipleLengthPrefixedSamples_l(buffer);
1365fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    } else {
136699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        if (isExif) {
136799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            ::write(mFd, &kTiffHeaderOffset, 4); // exif_tiff_header_offset field
136899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            mOffset += 4;
136999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        }
137099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
1371fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ::write(mFd,
1372fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang              (const uint8_t *)buffer->data() + buffer->range_offset(),
1373fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang              buffer->range_length());
137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1375fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        mOffset += buffer->range_length();
1376fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1378fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    *bytesWritten = mOffset - old_offset;
137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return old_offset;
138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
138120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
138203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
138303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (buffer->range_length() < 4) {
138403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return;
138503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
138603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
138703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    const uint8_t *ptr =
138803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
138903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
139003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
139103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        buffer->set_range(
139203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
139303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
139403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
139503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1396fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) {
139780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset();
139880f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *currentNalStart = dataStart;
139980f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *nextNalStart;
140080f78b773f92048944a850efb7b60629643370cdPraveen Chavan    const uint8_t *data = dataStart;
140180f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t nextNalSize;
1402986274d9c932d0df597d7809761b4cac2ac8e650Hangyu Kuang    size_t searchSize = buffer->range_length();
140380f78b773f92048944a850efb7b60629643370cdPraveen Chavan
140480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    while (getNextNALUnit(&data, &searchSize, &nextNalStart,
140580f78b773f92048944a850efb7b60629643370cdPraveen Chavan            &nextNalSize, true) == OK) {
140610cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar        size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */;
140780f78b773f92048944a850efb7b60629643370cdPraveen Chavan        MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize);
140880f78b773f92048944a850efb7b60629643370cdPraveen Chavan        addLengthPrefixedSample_l(nalBuf);
140980f78b773f92048944a850efb7b60629643370cdPraveen Chavan        nalBuf->release();
141080f78b773f92048944a850efb7b60629643370cdPraveen Chavan
141180f78b773f92048944a850efb7b60629643370cdPraveen Chavan        currentNalStart = nextNalStart;
141280f78b773f92048944a850efb7b60629643370cdPraveen Chavan    }
141380f78b773f92048944a850efb7b60629643370cdPraveen Chavan
141480f78b773f92048944a850efb7b60629643370cdPraveen Chavan    size_t currentNalOffset = currentNalStart - dataStart;
141580f78b773f92048944a850efb7b60629643370cdPraveen Chavan    buffer->set_range(buffer->range_offset() + currentNalOffset,
141680f78b773f92048944a850efb7b60629643370cdPraveen Chavan            buffer->range_length() - currentNalOffset);
141780f78b773f92048944a850efb7b60629643370cdPraveen Chavan    addLengthPrefixedSample_l(buffer);
141880f78b773f92048944a850efb7b60629643370cdPraveen Chavan}
141980f78b773f92048944a850efb7b60629643370cdPraveen Chavan
1420fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
142130ab66297501757d745b9ae10da61adcd891f497Andreas Huber    size_t length = buffer->range_length();
142203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
1423b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mUse4ByteNalLength) {
1424b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 24;
1425c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1426b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 16) & 0xff;
1427c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1428b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = (length >> 8) & 0xff;
1429c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1430b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1431c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1432c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong
1433c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd,
1434c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              (const uint8_t *)buffer->data() + buffer->range_offset(),
1435c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong              length);
1436b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
1437b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 4;
1438b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
1439b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross        CHECK_LT(length, 65536u);
144030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
1441b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        uint8_t x = length >> 8;
1442c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1443b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        x = length & 0xff;
1444c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, &x, 1);
1445c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
1446b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        mOffset += length + 2;
1447b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
144830ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
144930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
14507837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write(
1451674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        const void *ptr, size_t size, size_t nmemb) {
14527837c17063a4c50bc856ba59418516fdab731de7James Dong
14537837c17063a4c50bc856ba59418516fdab731de7James Dong    const size_t bytes = size * nmemb;
1454720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    if (mWriteBoxToMemory) {
14557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1456720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        off64_t boxSize = 8 + mInMemoryCacheOffset + bytes;
1457720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        if (boxSize > mInMemoryCacheSize) {
1458720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            // The reserved free space at the beginning of the file is not big
1459720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            // enough. Boxes should be written to the end of the file from now
1460720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            // on, but not to the in-memory cache.
14617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1462720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            // We write partial box that is in the memory to the file first.
1463c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            for (List<off64_t>::iterator it = mBoxes.begin();
14647837c17063a4c50bc856ba59418516fdab731de7James Dong                 it != mBoxes.end(); ++it) {
14657837c17063a4c50bc856ba59418516fdab731de7James Dong                (*it) += mOffset;
14667837c17063a4c50bc856ba59418516fdab731de7James Dong            }
1467674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong            lseek64(mFd, mOffset, SEEK_SET);
1468720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            ::write(mFd, mInMemoryCache, mInMemoryCacheOffset);
14697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong            ::write(mFd, ptr, bytes);
1470720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mOffset += (bytes + mInMemoryCacheOffset);
14717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong
1472720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            // All subsequent boxes will be written to the end of the file.
1473720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mWriteBoxToMemory = false;
14747837c17063a4c50bc856ba59418516fdab731de7James Dong        } else {
1475720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            memcpy(mInMemoryCache + mInMemoryCacheOffset, ptr, bytes);
1476720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mInMemoryCacheOffset += bytes;
14777837c17063a4c50bc856ba59418516fdab731de7James Dong        }
14787837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1479674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        ::write(mFd, ptr, size * nmemb);
14807837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset += bytes;
14817837c17063a4c50bc856ba59418516fdab731de7James Dong    }
14827837c17063a4c50bc856ba59418516fdab731de7James Dong    return bytes;
14837837c17063a4c50bc856ba59418516fdab731de7James Dong}
14847837c17063a4c50bc856ba59418516fdab731de7James Dong
1485e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) {
1486720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mBoxes.push_back(mWriteBoxToMemory?
1487720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mInMemoryCacheOffset: mOffset);
1488e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
1489e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);
1490e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(id);
1491e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1492e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
149320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) {
1494b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_EQ(strlen(fourcc), 4u);
149520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1496720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    mBoxes.push_back(mWriteBoxToMemory?
1497720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang            mInMemoryCacheOffset: mOffset);
149820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeInt32(0);
150020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    writeFourcc(fourcc);
150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() {
15040c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mBoxes.empty());
150520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1506c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = *--mBoxes.end();
150720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mBoxes.erase(--mBoxes.end());
150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1509720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    if (mWriteBoxToMemory) {
1510720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        int32_t x = htonl(mInMemoryCacheOffset - offset);
1511720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang        memcpy(mInMemoryCache + offset, &x, 4);
15127837c17063a4c50bc856ba59418516fdab731de7James Dong    } else {
1513c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, offset, SEEK_SET);
15147837c17063a4c50bc856ba59418516fdab731de7James Dong        writeInt32(mOffset - offset);
15157837c17063a4c50bc856ba59418516fdab731de7James Dong        mOffset -= 4;
1516c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        lseek64(mFd, mOffset, SEEK_SET);
15177837c17063a4c50bc856ba59418516fdab731de7James Dong    }
151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) {
1521674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 1);
152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) {
152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htons(x);
1526674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 2);
152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) {
153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = htonl(x);
1531674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 4);
153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) {
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    x = hton64(x);
1536674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(&x, 1, 8);
153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) {
154020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t n = strlen(s);
1541674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, n + 1);
154220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
154320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
154420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) {
1545b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_EQ(strlen(s), 4u);
1546674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(s, 1, 4);
154720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
154820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
154907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
155007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format
155107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) {
155207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
155307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
155407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
155507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
155607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[9];
155707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
155807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
155907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%c%.2d.", sign, wholePart);
156007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
156107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 5, "%+.2d.", wholePart);
156207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
156307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
156407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
156507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
156607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
156707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
156807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
156907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[4], 5, "%.4d", fractionalPart);
157007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
157107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
157207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 8);
157307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
157407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
157507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format
157607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) {
157707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    bool isNegative = (degreex10000 < 0);
157807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char sign = isNegative? '-': '+';
157907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
158007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the whole part
158107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    char str[10];
158207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int wholePart = degreex10000 / 10000;
158307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (wholePart == 0) {
158407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%c%.3d.", sign, wholePart);
158507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    } else {
158607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        snprintf(str, 6, "%+.3d.", wholePart);
158707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
158807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
158907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Handle the fractional part
159007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    int fractionalPart = degreex10000 - (wholePart * 10000);
159107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (fractionalPart < 0) {
159207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        fractionalPart = -fractionalPart;
159307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
159407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    snprintf(&str[5], 5, "%.4d", fractionalPart);
159507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
159607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Do not write the null terminator
159707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    write(str, 1, 9);
159807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
159907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
160007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
160107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
160207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and
160307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000.
160407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and
160507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180]
160607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
160707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
160807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    // Is latitude or longitude out of range?
160907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
161007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
161107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong        return BAD_VALUE;
161207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    }
161307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
161407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLatitudex10000 = latitudex10000;
161507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mLongitudex10000 = longitudex10000;
161607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    mAreGeoTagsAvailable = true;
16177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += 30;
161807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    return OK;
161907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
162007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
1621e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) {
1622e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (captureFps <= 0.0f) {
1623e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return BAD_VALUE;
1624e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
1625e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
16267c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
16277c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
16287c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
1629e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    return OK;
1630e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
1631e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
16324dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) {
16334dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 9) {
16344dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        return BAD_VALUE;
16354dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
16364dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
16374dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    if (layerCount > 0) {
16384dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount);
16394dbff11975e737482537e1636051690188f3fbc4Praveen Chavan        mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32;
16404dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    }
16414dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
16424dbff11975e737482537e1636051690188f3fbc4Praveen Chavan    return OK;
16434dbff11975e737482537e1636051690188f3fbc4Praveen Chavan}
16444dbff11975e737482537e1636051690188f3fbc4Praveen Chavan
1645fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::notifyApproachingLimit() {
1646fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock autolock(mLock);
1647fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // Only notify once.
1648fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mSendNotify) {
1649fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return;
1650fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1651fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGW("Recorded file size is approaching limit %" PRId64 "bytes",
1652fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mMaxFileSizeLimitBytes);
1653fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING, 0);
1654fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mSendNotify = true;
1655fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1656fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
165720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) {
1658674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    write(data, 1, size);
165920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
166020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
166178a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const {
166278a1a286f736888ae7af8860b2c424af0d978848James Dong    return mStreamableFile;
166378a1a286f736888ae7af8860b2c424af0d978848James Dong}
166478a1a286f736888ae7af8860b2c424af0d978848James Dong
1665d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() {
1666d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1667d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileSizeLimitBytes == 0) {
1668d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1669d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1670720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    int64_t nTotalBytesEstimate = static_cast<int64_t>(mInMemoryCacheSize);
1671d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1672d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1673d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1674d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
16751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
167677e8ae9967a078770416619e99ddb5b010def312James Dong    if (!mStreamableFile) {
167777e8ae9967a078770416619e99ddb5b010def312James Dong        // Add 1024 bytes as error tolerance
167877e8ae9967a078770416619e99ddb5b010def312James Dong        return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes;
167977e8ae9967a078770416619e99ddb5b010def312James Dong    }
1680fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1681acd234bba9f048971d66890009eeff9a8db94be3James Dong    // Be conservative in the estimate: do not exceed 95% of
1682acd234bba9f048971d66890009eeff9a8db94be3James Dong    // the target file limit. For small target file size limit, though,
1683acd234bba9f048971d66890009eeff9a8db94be3James Dong    // this will not help.
1684acd234bba9f048971d66890009eeff9a8db94be3James Dong    return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
1685d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1686d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1687fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangbool MPEG4Writer::approachingFileSizeLimit() {
1688fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    // No limit
1689fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mMaxFileSizeLimitBytes == 0) {
1690fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return false;
1691fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1692fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1693720e24cfe430e1719c5defb9a1f41a6b63b02eafChong Zhang    int64_t nTotalBytesEstimate = static_cast<int64_t>(mInMemoryCacheSize);
1694fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    for (List<Track *>::iterator it = mTracks.begin();
1695fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         it != mTracks.end(); ++it) {
1696fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
1697fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1698fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1699fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (!mStreamableFile) {
1700fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // Add 1024 bytes as error tolerance
1701fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return nTotalBytesEstimate + 1024 >= (90 * mMaxFileSizeLimitBytes) / 100;
1702fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1703fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1704fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return (nTotalBytesEstimate >= (90 * mMaxFileSizeLimitBytes) / 100);
1705fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1706fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1707d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() {
1708d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    // No limit
1709d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    if (mMaxFileDurationLimitUs == 0) {
1710d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        return false;
1711d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1712d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
1713d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    for (List<Track *>::iterator it = mTracks.begin();
1714d599cd4573b5a2d5914c5040e0565ef866749b77James Dong         it != mTracks.end(); ++it) {
1715fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!(*it)->isHeic() && (*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
1716d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            return true;
1717d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
1718d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    }
1719d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return false;
1720d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
1721d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
172225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() {
172325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    bool allDone = true;
172425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    for (List<Track *>::iterator it = mTracks.begin();
172525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber         it != mTracks.end(); ++it) {
172625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        if (!(*it)->reachedEOS()) {
172725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            allDone = false;
172825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber            break;
172925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        }
173025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
173125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
173225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return allDone;
173325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
173425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
1735f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
1736a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("setStartTimestampUs: %" PRId64, timeUs);
173743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GE(timeUs, 0ll);
17383c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
1739065d1aff96818df54456053f1574aec8a234d0deJames Dong    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
1740f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimestampUs = timeUs;
1741a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs);
17423c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    }
17433c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
17443c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
1745f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() {
17463c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    Mutex::Autolock autoLock(mLock);
17473c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong    return mStartTimestampUs;
17483c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong}
17493c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong
175058ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() {
175158ae9c530247668f8af36e30d228c716c226b3d4James Dong    Mutex::Autolock autolock(mLock);
175258ae9c530247668f8af36e30d228c716c226b3d4James Dong    return mTracks.size();
175358ae9c530247668f8af36e30d228c716c226b3d4James Dong}
175458ae9c530247668f8af36e30d228c716c226b3d4James Dong
175520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
175620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
175720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track(
1758ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kang        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
175920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mOwner(owner),
176025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mMeta(source->getFormat()),
176120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSource(source),
176220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDone(false),
1763a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mPaused(false),
1764a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong      mResumed(false),
1765eaae38445a340c4857c1c5569475879a728e63b7James Dong      mStarted(false),
1766fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mGotStartKeyFrame(false),
17679db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang      mIsMalformed(false),
1768bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong      mTrackId(trackId),
1769c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong      mTrackDurationUs(0),
1770956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mEstimatedTrackSizeBytes(0),
1771be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong      mSamplesHaveSameSize(true),
1772c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1773c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1774c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)),
1775c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)),
1776c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
1777c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
1778c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar      mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
1779230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang      mMinCttsOffsetTimeUs(0),
1780230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang      mMinCttsOffsetTicks(0),
1781230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang      mMaxCttsOffsetTicks(0),
178220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCodecSpecificData(NULL),
178325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber      mCodecSpecificDataSize(0),
1784548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber      mGotAllCodecSpecificData(false),
178513f6284305e4b27395a23db7882d670bdb1bcae1James Dong      mReachedEOS(false),
1786a9292fe1c19e8a9b43398ba3d69284c215d7589fRobert Shih      mStartTimestampUs(-1),
1787fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mRotation(0),
178899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang      mDimgRefs("dimg"),
178999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang      mCdscRefs("cdsc"),
179099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang      mImageItemId(0),
1791fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mIsPrimary(0),
1792fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mWidth(0),
1793fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mHeight(0),
179467d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang      mTileWidth(0),
179567d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang      mTileHeight(0),
1796fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mGridRows(0),
1797fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mGridCols(0),
1798fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mNumTiles(1),
1799fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang      mTileIndex(0) {
180019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    getCodecSpecificDataFromInputFormatIfPossible();
18018f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
18021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    const char *mime;
18031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mMeta->findCString(kKeyMIMEType, &mime);
18041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
18059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
18061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsAudio = !strncasecmp(mime, "audio/", 6);
180725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mIsVideo = !strncasecmp(mime, "video/", 6);
1808fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mIsHeic = !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC);
18091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
18101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
18111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
1812b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    // store temporal layer count
181325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo) {
1814b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        int32_t count;
1815b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) {
1816b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar            mOwner->setTemporalLayerCount(count);
1817b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar        }
1818b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar    }
1819b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar
1820fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (!mIsHeic) {
1821fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        setTimeScale();
1822fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    } else {
1823fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        CHECK(mMeta->findInt32(kKeyWidth, &mWidth) && (mWidth > 0));
1824fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        CHECK(mMeta->findInt32(kKeyHeight, &mHeight) && (mHeight > 0));
1825fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
182667d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang        int32_t tileWidth, tileHeight, gridRows, gridCols;
182767d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang        if (mMeta->findInt32(kKeyTileWidth, &tileWidth) && (tileWidth > 0) &&
182867d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang            mMeta->findInt32(kKeyTileHeight, &tileHeight) && (tileHeight > 0) &&
1829fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mMeta->findInt32(kKeyGridRows, &gridRows) && (gridRows > 0) &&
1830fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mMeta->findInt32(kKeyGridCols, &gridCols) && (gridCols > 0)) {
183167d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang            mTileWidth = tileWidth;
183267d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang            mTileHeight = tileHeight;
1833fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mGridRows = gridRows;
1834fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mGridCols = gridCols;
1835fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mNumTiles = gridRows * gridCols;
1836fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1837fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!mMeta->findInt32(kKeyTrackIsDefault, &mIsPrimary)) {
1838fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mIsPrimary = false;
1839fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
1840fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
1841c059860c73678a202bfa33062723e8f82fb779d9James Dong}
1842c059860c73678a202bfa33062723e8f82fb779d9James Dong
1843fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang// Clear all the internal states except the CSD data.
1844fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::Track::resetInternal() {
1845fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mDone = false;
1846fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mPaused = false;
1847fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mResumed = false;
1848fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mStarted = false;
1849fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mGotStartKeyFrame = false;
1850fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mIsMalformed = false;
1851fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mTrackDurationUs = 0;
1852fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mEstimatedTrackSizeBytes = 0;
1853fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mSamplesHaveSameSize = 0;
1854fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStszTableEntries != NULL) {
1855fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStszTableEntries;
1856fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1857fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1858fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1859fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStcoTableEntries != NULL) {
1860fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStcoTableEntries;
1861fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1862fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1863fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mCo64TableEntries != NULL) {
1864fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mCo64TableEntries;
1865fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000);
1866fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1867fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1868fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStscTableEntries != NULL) {
1869fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStscTableEntries;
1870fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000);
1871fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1872fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mStssTableEntries != NULL) {
1873fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mStssTableEntries;
1874fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000);
1875fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1876fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mSttsTableEntries != NULL) {
1877fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mSttsTableEntries;
1878fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
1879fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1880fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      if (mCttsTableEntries != NULL) {
1881fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         delete mCttsTableEntries;
1882fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang         mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000);
1883fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      }
1884fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang      mReachedEOS = false;
1885fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1886fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
18871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() {
1888fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
18891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1890fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (!isHeic() && !mOwner->isFileStreamable()) {
1891fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
1892fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                                ? mStcoTableEntries->count()
1893fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                                : mCo64TableEntries->count());
1894fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
1895fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
18961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
189778a1a286f736888ae7af8860b2c424af0d978848James Dong        // Reserved free space is not large enough to hold
189878a1a286f736888ae7af8860b2c424af0d978848James Dong        // all meta data and thus wasted.
1899c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
1900c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mStssTableEntries->count() * 4 +   // stss box size
1901c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mSttsTableEntries->count() * 8 +   // stts box size
1902c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                                    mCttsTableEntries->count() * 8 +   // ctts box size
190378a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stcoBoxSizeBytes +           // stco box size
190478a1a286f736888ae7af8860b2c424af0d978848James Dong                                    stszBoxSizeBytes;            // stsz box size
190578a1a286f736888ae7af8860b2c424af0d978848James Dong    }
19061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
19071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
19081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry(
19091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        size_t chunkId, size_t sampleId) {
1910fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mStscTableEntries->add(htonl(chunkId));
1911fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mStscTableEntries->add(htonl(sampleId));
1912fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mStscTableEntries->add(htonl(1));
19131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
19141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
19151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
1916c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->add(htonl(sampleId));
19171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
19181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
19191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry(
192079761ab096f57c3027fad9556c2bc436672d614eJames Dong        size_t sampleCount, int32_t duration) {
19211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
19225a217fba010e801c255503602bda4b86ac5a6ac9James Dong    if (duration == 0) {
1923377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("0-duration samples found: %zu", sampleCount);
19245a217fba010e801c255503602bda4b86ac5a6ac9James Dong    }
1925c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(sampleCount));
1926c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->add(htonl(duration));
19271f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
19281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
1929965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry(
1930965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        size_t sampleCount, int32_t duration) {
1931965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
193225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!mIsVideo) {
1933965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
1934965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
1935c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(sampleCount));
1936c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->add(htonl(duration));
1937965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
1938965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
1939fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::setNextFd(int fd) {
1940fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGV("addNextFd");
1941fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    Mutex::Autolock l(mLock);
1942fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mLooper == NULL) {
1943fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mReflector = new AHandlerReflector<MPEG4Writer>(this);
1944fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper = new ALooper;
1945fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper->registerHandler(mReflector);
1946fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mLooper->start();
1947fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1948fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
1949fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (mNextFd != -1) {
1950fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // No need to set a new FD yet.
1951fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        return INVALID_OPERATION;
1952fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
1953fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    mNextFd = fd;
1954fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    return OK;
1955fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
1956fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
195799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhangbool MPEG4Writer::Track::isExifData(const MediaBufferBase *buffer) const {
195899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    return mIsHeic
195999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            && (buffer->range_length() > sizeof(kExifHeader))
196099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            && !memcmp((uint8_t *)buffer->data() + buffer->range_offset(),
196199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                    kExifHeader, sizeof(kExifHeader));
196299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang}
196399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
1964c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) {
1965fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    CHECK(!mIsHeic);
1966c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mOwner->use32BitFileOffset()) {
1967c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        uint32_t value = offset;
1968c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->add(htonl(value));
1969c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
1970c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->add(hton64(offset));
1971c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    }
19721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong}
19731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
197499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhangvoid MPEG4Writer::Track::addItemOffsetAndSize(off64_t offset, size_t size, bool isExif) {
1975fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    CHECK(mIsHeic);
1976fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
1977fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (offset > UINT32_MAX || size > UINT32_MAX) {
1978fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGE("offset or size is out of range: %lld, %lld",
1979fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                (long long) offset, (long long) size);
1980fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        mIsMalformed = true;
1981fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
1982fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mIsMalformed) {
1983fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        return;
1984fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
198599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
198699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    if (isExif) {
198799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang         mCdscRefs.value.push_back(mOwner->addItem_l({
198899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .itemType = "Exif",
198999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .isPrimary = false,
199099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .isHidden = false,
199199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .offset = (uint32_t)offset,
199299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .size = (uint32_t)size,
199399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        }));
199499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        return;
199599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    }
199699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
1997fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mTileIndex >= mNumTiles) {
1998fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGW("Ignoring excess tiles!");
1999fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        return;
2000fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
2001fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
200256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // Rotation angle in HEIF is CCW, framework angle is CW.
200356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    int32_t heifRotation = 0;
200456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    switch(mRotation) {
200556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        case 90: heifRotation = 3; break;
200656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        case 180: heifRotation = 2; break;
200756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        case 270: heifRotation = 1; break;
200856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        default: break; // don't set if invalid
200956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    }
201056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
201199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    bool hasGrid = (mTileWidth > 0);
201256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
2013fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mProperties.empty()) {
2014fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        mProperties.push_back(mOwner->addProperty_l({
2015fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            .type = FOURCC('h', 'v', 'c', 'C'),
2016fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            .hvcc = ABuffer::CreateAsCopy(mCodecSpecificData, mCodecSpecificDataSize)
2017fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }));
2018fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
2019fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        mProperties.push_back(mOwner->addProperty_l({
2020fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            .type = FOURCC('i', 's', 'p', 'e'),
202167d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang            .width = hasGrid ? mTileWidth : mWidth,
202267d5b91f2fa0b106c038e642225e3b538db2be2eChong Zhang            .height = hasGrid ? mTileHeight : mHeight,
2023fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }));
202456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
202556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        if (!hasGrid && heifRotation > 0) {
202656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            mProperties.push_back(mOwner->addProperty_l({
202756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                .type = FOURCC('i', 'r', 'o', 't'),
202856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                .rotation = heifRotation,
202956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            }));
203056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        }
2031fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
2032fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
2033fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mTileIndex++;
203456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    if (hasGrid) {
203599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        mDimgRefs.value.push_back(mOwner->addItem_l({
203699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .itemType = "hvc1",
203799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .isPrimary = false,
203899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .isHidden = true,
203999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .offset = (uint32_t)offset,
204099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .size = (uint32_t)size,
204199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .properties = mProperties,
204299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        }));
2043fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
2044fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mTileIndex == mNumTiles) {
2045fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mProperties.clear();
2046fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mProperties.push_back(mOwner->addProperty_l({
2047fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .type = FOURCC('i', 's', 'p', 'e'),
2048fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .width = mWidth,
2049fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .height = mHeight,
2050fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }));
205156eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            if (heifRotation > 0) {
205256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                mProperties.push_back(mOwner->addProperty_l({
205356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                    .type = FOURCC('i', 'r', 'o', 't'),
205456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                    .rotation = heifRotation,
205556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                }));
205656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            }
205799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            mImageItemId = mOwner->addItem_l({
2058fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .itemType = "grid",
2059fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .isPrimary = (mIsPrimary != 0),
2060fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .isHidden = false,
2061fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .rows = (uint32_t)mGridRows,
2062fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .cols = (uint32_t)mGridCols,
2063fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .width = (uint32_t)mWidth,
2064fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .height = (uint32_t)mHeight,
2065fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                .properties = mProperties,
2066fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            });
2067fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
206899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    } else {
206999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        mImageItemId = mOwner->addItem_l({
207099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .itemType = "hvc1",
207199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .isPrimary = (mIsPrimary != 0),
207299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .isHidden = false,
207399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .offset = (uint32_t)offset,
207499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .size = (uint32_t)size,
207599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            .properties = mProperties,
207699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        });
207799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    }
207899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang}
207999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
208099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang// Flush out the item refs for this track. Note that it must be called after the
208199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang// writer thread has stopped, because there might be pending items in the last
208299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang// few chunks written by the writer thread (as opposed to the track). In particular,
208399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang// it affects the 'dimg' refs for tiled image, as we only have the refs after the
208499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang// last tile sample is written.
208599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhangvoid MPEG4Writer::Track::flushItemRefs() {
208699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    CHECK(mIsHeic);
208799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
208899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    if (mImageItemId > 0) {
208999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        mOwner->addRefs_l(mImageItemId, mDimgRefs);
209099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        mOwner->addRefs_l(mImageItemId, mCdscRefs);
2091fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
2092fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
2093fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
2094c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() {
20953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setTimeScale");
2096c059860c73678a202bfa33062723e8f82fb779d9James Dong    // Default time scale
2097c059860c73678a202bfa33062723e8f82fb779d9James Dong    mTimeScale = 90000;
2098c059860c73678a202bfa33062723e8f82fb779d9James Dong
2099c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mIsAudio) {
2100c059860c73678a202bfa33062723e8f82fb779d9James Dong        // Use the sampling rate as the default time scale for audio track.
2101c059860c73678a202bfa33062723e8f82fb779d9James Dong        int32_t sampleRate;
2102c059860c73678a202bfa33062723e8f82fb779d9James Dong        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
2103c059860c73678a202bfa33062723e8f82fb779d9James Dong        CHECK(success);
2104c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = sampleRate;
2105c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
2106c059860c73678a202bfa33062723e8f82fb779d9James Dong
2107c059860c73678a202bfa33062723e8f82fb779d9James Dong    // If someone would like to overwrite the timescale, use user-supplied value.
2108c059860c73678a202bfa33062723e8f82fb779d9James Dong    int32_t timeScale;
2109c059860c73678a202bfa33062723e8f82fb779d9James Dong    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
2110c059860c73678a202bfa33062723e8f82fb779d9James Dong        mTimeScale = timeScale;
2111c059860c73678a202bfa33062723e8f82fb779d9James Dong    }
2112c059860c73678a202bfa33062723e8f82fb779d9James Dong
211343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK_GT(mTimeScale, 0);
211419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber}
211519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
2116fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::onMessageReceived(const sp<AMessage> &msg) {
2117fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    switch (msg->what()) {
2118fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        case kWhatSwitch:
2119fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        {
2120fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            finishCurrentSession();
2121fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mLock.lock();
2122fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            int fd = mNextFd;
2123fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mNextFd = -1;
2124fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mLock.unlock();
21255ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang            initInternal(fd, false /*isFirstSession*/);
2126fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            start(mStartMeta.get());
2127fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mSwitchPending = false;
2128fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED, 0);
2129fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            break;
2130fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
2131fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        default:
2132fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        TRESPASS();
2133fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
2134fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang}
2135fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
213619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
213719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    const char *mime;
2138fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
213919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
214019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
21419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint32_t type;
21429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const void *data = NULL;
21439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t size = 0;
214419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
21459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyAVCC, &type, &data, &size);
2146fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC) ||
2147fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang               !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) {
21489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mMeta->findData(kKeyHVCC, &type, &data, &size);
214919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
215019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
215119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
215219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            ESDS esds(data, size);
2153212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa            if (esds.getCodecSpecificInfo(&data, &size) == OK &&
2154212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa                    data != NULL &&
2155212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa                    copyCodecSpecificData((uint8_t*)data, size) == OK) {
2156212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa                mGotAllCodecSpecificData = true;
215719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber            }
2158212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa            return;
215919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        }
216019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
21619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
21629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mGotAllCodecSpecificData = true;
21639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
216420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
216520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
216620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() {
216720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    stop();
216820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStszTableEntries;
2170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStcoTableEntries;
2171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCo64TableEntries;
2172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStscTableEntries;
2173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mSttsTableEntries;
2174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mStssTableEntries;
2175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    delete mCttsTableEntries;
2176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
2177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries = NULL;
2178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStcoTableEntries = NULL;
2179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCo64TableEntries = NULL;
2180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries = NULL;
2181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries = NULL;
2182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries = NULL;
2183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries = NULL;
2184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
218520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodecSpecificData != NULL) {
218620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        free(mCodecSpecificData);
218720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecSpecificData = NULL;
218820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
218920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
219020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
219193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
21923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initTrackingProgressStatus");
219393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mPreviousTrackTimeUs = -1;
219493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackingProgressStatus = false;
219593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    mTrackEveryTimeDurationUs = 0;
219693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    {
219793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        int64_t timeUs;
219893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
2199a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs);
220093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackEveryTimeDurationUs = timeUs;
220193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            mTrackingProgressStatus = true;
220293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
220393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
220493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
220593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
22061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static
22071c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) {
22083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("ThreadWrapper: %p", me);
22091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
22101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    writer->threadFunc();
22111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return NULL;
22121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
22131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22141c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) {
22153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk: %p", chunk.mTrack);
22161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Mutex::Autolock autolock(mLock);
22171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    CHECK_EQ(mDone, false);
22181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
22201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
22211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (chunk.mTrack == it->mTrack) {  // Found owner
22231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            it->mChunks.push_back(chunk);
22241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.signal();
22251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            return;
22261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
22271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
22281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
222943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    CHECK(!"Received a chunk for a unknown track");
22301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
22311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2232fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) {
2233a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("writeChunkToFile: %" PRId64 " from %s track",
223425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        chunk->mTimeStampUs, chunk->mTrack->getTrackType());
2235fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2236fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    int32_t isFirstSample = true;
2237fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    while (!chunk->mSamples.empty()) {
2238fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
2239fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
224099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        int32_t isExif;
224199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        if (!(*it)->meta_data().findInt32(kKeyIsExif, &isExif)) {
224299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            isExif = 0;
224399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        }
224499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        bool usePrefix = chunk->mTrack->usePrefix() && !isExif;
224599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
2246fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        size_t bytesWritten;
224799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        off64_t offset = addSample_l(*it, usePrefix, isExif, &bytesWritten);
2248fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2249fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (chunk->mTrack->isHeic()) {
225099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            chunk->mTrack->addItemOffsetAndSize(offset, bytesWritten, isExif);
2251fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else if (isFirstSample) {
2252fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            chunk->mTrack->addChunkOffset(offset);
2253fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            isFirstSample = false;
22541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
22551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it)->release();
22571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        (*it) = NULL;
2258fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        chunk->mSamples.erase(it);
22591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2260fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    chunk->mSamples.clear();
22611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
22621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2263fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() {
22643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("writeAllChunks");
22651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    size_t outstandingChunks = 0;
226670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    Chunk chunk;
226770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    while (findChunkToWrite(&chunk)) {
2268e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong        writeChunkToFile(&chunk);
226970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        ++outstandingChunks;
22701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
227170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
227270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    sendSessionSummary();
227370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
22741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mChunkInfos.clear();
2275377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    ALOGD("%zu chunks are written in the last batch", outstandingChunks);
22761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
22771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2278fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
22793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("findChunkToWrite");
22801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
22821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Track *track = NULL;
22831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
22841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
22851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (!it->mChunks.empty()) {
22861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            List<Chunk>::iterator chunkIt = it->mChunks.begin();
22871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            if (chunkIt->mTimeStampUs < minTimestampUs) {
22881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                minTimestampUs = chunkIt->mTimeStampUs;
22891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                track = it->mTrack;
22901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            }
22911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
22921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
22931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (track == NULL) {
22953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Nothing to be written after all");
2296fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        return false;
22971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
22981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
22991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    if (mIsFirstChunk) {
23001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mIsFirstChunk = false;
23011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2302fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
23031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
23041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mChunkInfos.end(); ++it) {
23051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        if (it->mTrack == track) {
2306fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            *chunk = *(it->mChunks.begin());
2307fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            it->mChunks.erase(it->mChunks.begin());
2308fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            CHECK_EQ(chunk->mTrack, track);
230970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
231070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t interChunkTimeUs =
231170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
231270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
231370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                it->mMaxInterChunkDurUs = interChunkTimeUs;
231470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            }
231570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
2316fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            return true;
23171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
23181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2319fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2320fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    return false;
23211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
23221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
23231c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() {
23243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("threadFunc");
23251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2326a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
2327fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2328fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    Mutex::Autolock autoLock(mLock);
23291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    while (!mDone) {
2330fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        Chunk chunk;
2331fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        bool chunkFound = false;
2332fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2333fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
23341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            mChunkReadyCondition.wait(mLock);
23351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        }
23361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
2337de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // In real time recording mode, write without holding the lock in order
2338de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // to reduce the blocking time for media track threads.
2339de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // Otherwise, hold the lock until the existing chunks get written to the
2340de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        // file.
2341fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        if (chunkFound) {
2342de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
2343de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.unlock();
2344de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
2345fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong            writeChunkToFile(&chunk);
2346de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            if (mIsRealTimeRecording) {
2347de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui                mLock.lock();
2348de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui            }
2349fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong        }
23501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
2351fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong
2352fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong    writeAllChunks();
23531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
23541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
23551c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() {
23563856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startWriterThread");
23571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
23581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mDone = false;
23591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mIsFirstChunk = true;
2360e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    mDriftTimeUs = 0;
23611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    for (List<Track *>::iterator it = mTracks.begin();
23621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong         it != mTracks.end(); ++it) {
23631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        ChunkInfo info;
23641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        info.mTrack = *it;
236570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mPrevChunkTimestampUs = 0;
236670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        info.mMaxInterChunkDurUs = 0;
23671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong        mChunkInfos.push_back(info);
23681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    }
23691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
23701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_t attr;
23711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_init(&attr);
23721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
23731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_create(&mThread, &attr, ThreadWrapper, this);
23741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    pthread_attr_destroy(&attr);
2375411ba422e3635d534928ffd81abf54f4f291c739James Dong    mWriterThreadStarted = true;
23761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    return OK;
23771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong}
23781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
23791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
238093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) {
2381a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    if (!mDone && mPaused) {
2382a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mPaused = false;
2383a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        mResumed = true;
2384a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        return OK;
2385a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    }
238625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
238793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    int64_t startTimeUs;
238819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
238919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber        startTimeUs = 0;
239019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber    }
239170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong    mStartTimeRealUs = startTimeUs;
239219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber
239313f6284305e4b27395a23db7882d670bdb1bcae1James Dong    int32_t rotationDegrees;
239456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    if ((mIsVideo || mIsHeic) && params &&
239556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            params->findInt32(kKeyRotation, &rotationDegrees)) {
239613f6284305e4b27395a23db7882d670bdb1bcae1James Dong        mRotation = rotationDegrees;
239713f6284305e4b27395a23db7882d670bdb1bcae1James Dong    }
239813f6284305e4b27395a23db7882d670bdb1bcae1James Dong
239993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    initTrackingProgressStatus(params);
240093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
2401f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    sp<MetaData> meta = new MetaData;
2402de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
2403a472613aec322e25891abf5c77bf3f7e3c244920James Dong        /*
2404a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * This extra delay of accepting incoming audio/video signals
2405a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * helps to align a/v start time at the beginning of a recording
2406a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * session, and it also helps eliminate the "recording" sound for
2407a472613aec322e25891abf5c77bf3f7e3c244920James Dong         * camcorder applications.
2408a472613aec322e25891abf5c77bf3f7e3c244920James Dong         *
240986b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * If client does not set the start time offset, we fall back to
241086b7f47aa7482424cf8fd248f1315311919be3b0James Dong         * use the default initial delay value.
2411a472613aec322e25891abf5c77bf3f7e3c244920James Dong         */
241286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
241386b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
241486b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
241586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
241686b7f47aa7482424cf8fd248f1315311919be3b0James Dong        startTimeUs += startTimeOffsetUs;
2417a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs);
2418a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
2419a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2420f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    meta->setInt64(kKeyTime, startTimeUs);
2421a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2422f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    status_t err = mSource->start(meta.get());
242325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    if (err != OK) {
242425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        mDone = mReachedEOS = true;
242525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber        return err;
242625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    }
242720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
242820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_t attr;
242920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_init(&attr);
243020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
243120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
243220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDone = false;
2433eaae38445a340c4857c1c5569475879a728e63b7James Dong    mStarted = true;
2434c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong    mTrackDurationUs = 0;
243525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = false;
2436956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mEstimatedTrackSizeBytes = 0;
24371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong    mMdatSizeBytes = 0;
243843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mMaxChunkDurationUs = 0;
2439826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar    mLastDecodingTimeUs = -1;
244020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
244125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    pthread_create(&mThread, &attr, ThreadWrapper, this);
244220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_attr_destroy(&attr);
244325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
244425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return OK;
244520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
244620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
244737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() {
2448a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    mPaused = true;
244937187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
2450a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong}
2451a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2452fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::Track::stop(bool stopSource) {
2453fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGD("%s track stopping. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop");
2454eaae38445a340c4857c1c5569475879a728e63b7James Dong    if (!mStarted) {
245529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Stop() called but track is not started");
2456eaae38445a340c4857c1c5569475879a728e63b7James Dong        return ERROR_END_OF_STREAM;
2457eaae38445a340c4857c1c5569475879a728e63b7James Dong    }
2458eaae38445a340c4857c1c5569475879a728e63b7James Dong
245920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mDone) {
246037187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
246120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
2462f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
2463fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    if (stopSource) {
2464fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGD("%s track source stopping", getTrackType());
2465fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        mSource->stop();
2466fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        ALOGD("%s track source stopped", getTrackType());
2467fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    }
246872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2469f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    // Set mDone to be true after sucessfully stop mSource as mSource may be still outputting
2470f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    // buffers to the writer.
2471f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    mDone = true;
2472f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
247320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    void *dummy;
247420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    pthread_join(mThread, &dummy);
2475377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
247637187916a486504acaf83bea30147eb5fbf46ae5James Dong
2477fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang    ALOGD("%s track stopped. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop");
247837187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
247920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
248020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
248125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() {
248225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    return mReachedEOS;
248325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber}
248425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
248520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
248620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) {
248720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = static_cast<Track *>(me);
248820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
248937187916a486504acaf83bea30147eb5fbf46ae5James Dong    status_t err = track->threadEntry();
2490377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    return (void *)(uintptr_t)err;
249120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
249220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) {
24943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getNalUnitType: %d", byte);
24953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
24963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // nal_unit_type: 5-bit unsigned integer
24973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *type = (byte & 0x1F);
24983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
24993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet(
25013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
25023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseParamSet");
25043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    CHECK(type == kNalUnitTypeSeqParamSet ||
25053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong          type == kNalUnitTypePicParamSet);
25063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
250747d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar    const uint8_t *nextStartCode = findNextNalStartCode(data, length);
25083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    *paramSetLen = nextStartCode - data;
25093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (*paramSetLen == 0) {
251029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Param set is malformed, since its length is 0");
25113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return NULL;
25123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
25133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    AVCParamSet paramSet(*paramSetLen, data);
25153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (type == kNalUnitTypeSeqParamSet) {
25163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (*paramSetLen < 4) {
251729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Seq parameter set malformed");
25183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return NULL;
25193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
25203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mSeqParamSets.empty()) {
25213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc = data[1];
25223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileCompatible = data[2];
25233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mLevelIdc = data[3];
25243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
25253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (mProfileIdc != data[1] ||
25263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mProfileCompatible != data[2] ||
25273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                mLevelIdc != data[3]) {
252807b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                // COULD DO: set profile/level to the lowest required to support all SPSs
252929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Inconsistent profile/level found in seq parameter sets");
25303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return NULL;
25313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
25323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
25333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mSeqParamSets.push_back(paramSet);
25343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    } else {
25353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mPicParamSets.push_back(paramSet);
25363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
25373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return nextStartCode;
25383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
25393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData(
25413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
25423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("copyAVCCodecSpecificData");
25433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 2 bytes for each of the parameter set length field
25453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // plus the 7 bytes for the header
25469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 4 + 7);
25479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
25489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
25499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData(
25509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
25519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("copyHEVCCodecSpecificData");
25529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
25539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2)
25549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return copyCodecSpecificData(data, size, 23);
25559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
25569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
25579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData(
25589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, size_t minLength) {
25599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < minLength) {
2560377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
25613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return ERROR_MALFORMED;
25623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
25633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificData = malloc(size);
25659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
25669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
25679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
25689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
25699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = size;
25703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    memcpy(mCodecSpecificData, data, size);
25713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
25723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
25733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData(
25753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        const uint8_t *data, size_t size) {
25763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
25773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("parseAVCCodecSpecificData");
25783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data starts with a start code.
25793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // SPS and PPS are separated with start codes.
25803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Also, SPS must come before PPS
25813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    uint8_t type = kNalUnitTypeSeqParamSet;
25823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotSps = false;
25833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    bool gotPps = false;
25843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *tmp = data;
25853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    const uint8_t *nextStartCode = data;
25863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t bytesLeft = size;
25873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    size_t paramSetLen = 0;
25883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize = 0;
25893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
25903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        getNalUnitType(*(tmp + 4), &type);
25913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (type == kNalUnitTypeSeqParamSet) {
25923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (gotPps) {
259329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
25943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
25953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
25963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
25973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotSps = true;
25983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
25993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
26003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else if (type == kNalUnitTypePicParamSet) {
26013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotSps) {
260229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("SPS must come before PPS");
26033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                return ERROR_MALFORMED;
26043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
26053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            if (!gotPps) {
26063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong                gotPps = true;
26073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            }
26083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
26093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        } else {
261029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Only SPS and PPS Nal units are expected");
26113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
26123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
26133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
26143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nextStartCode == NULL) {
26153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
26163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
26173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
26183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Move on to find the next parameter set
26193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        bytesLeft -= nextStartCode - tmp;
26203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        tmp = nextStartCode;
26213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        mCodecSpecificDataSize += (2 + paramSetLen);
26223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
26233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
26243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
26253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of seq parameter sets
26263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nSeqParamSets = mSeqParamSets.size();
26273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets == 0) {
262829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find sequence parameter set");
26293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
26303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
26313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
26323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nSeqParamSets > 0x1F) {
2633377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets);
26343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
26353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
26363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
26373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
26383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
26393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the number of pic parameter sets
26403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        size_t nPicParamSets = mPicParamSets.size();
26413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets == 0) {
264229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Cound not find picture parameter set");
26433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
26443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
26453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (nPicParamSets > 0xFF) {
2646377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets);
26473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return ERROR_MALFORMED;
26483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
26493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
26501374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME:
26511374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
26521374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0
26531374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0
26543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    {
26553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // Check on the profiles
26563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // These profiles requires additional parameter set extensions
26573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        if (mProfileIdc == 100 || mProfileIdc == 110 ||
26583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            mProfileIdc == 122 || mProfileIdc == 144) {
265929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
26603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong            return BAD_VALUE;
26613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        }
26623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
26631374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif
26643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    return OK;
26653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong}
2666548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
266703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData(
266803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        const uint8_t *data, size_t size) {
2669548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber
267003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    if (mCodecSpecificData != NULL) {
267129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Already have codec specific data");
267203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
267303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
267403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
26753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (size < 4) {
2676377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGE("Codec specific data length too short: %zu", size);
267703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
267803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
267903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
26803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // Data is in the form of AVCCodecSpecificData
26813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (memcmp("\x00\x00\x00\x01", data, 4)) {
26823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        return copyAVCCodecSpecificData(data, size);
268303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
268403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
26853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    if (parseAVCCodecSpecificData(data, size) != OK) {
268603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        return ERROR_MALFORMED;
268703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    }
268803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
26893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // ISO 14496-15: AVC file format
26903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    mCodecSpecificDataSize += 7;  // 7 more bytes in the header
269103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    mCodecSpecificData = malloc(mCodecSpecificDataSize);
26929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
26939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
26949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
26959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
26969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
269703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    uint8_t *header = (uint8_t *)mCodecSpecificData;
26983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = 1;                     // version
26993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[1] = mProfileIdc;           // profile indication
27003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[2] = mProfileCompatible;    // profile compatibility
27013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[3] = mLevelIdc;
270203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
27033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
2704b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    if (mOwner->useNalLengthFour()) {
2705b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 3;  // length size == 4 bytes
2706b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    } else {
2707b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        header[4] = 0xfc | 1;  // length size == 2 bytes
2708b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    }
270903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
27103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 3-bit '111' followed by 5-bit numSequenceParameterSets
27113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nSequenceParamSets = mSeqParamSets.size();
27123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[5] = 0xe0 | nSequenceParamSets;
27133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 6;
27143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
27153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mSeqParamSets.end(); ++it) {
27163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit sequence parameter set length
27173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t seqParamSetLength = it->mLength;
27183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = seqParamSetLength >> 8;
27193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = seqParamSetLength & 0xff;
27203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
27213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // SPS NAL unit (sequence parameter length bytes)
27223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, seqParamSetLength);
27233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + seqParamSetLength);
27243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
27253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
27263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    // 8-bit nPictureParameterSets
27273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    int nPictureParamSets = mPicParamSets.size();
27283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header[0] = nPictureParamSets;
27293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    header += 1;
27303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
27313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong         it != mPicParamSets.end(); ++it) {
27323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // 16-bit picture parameter set length
27333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        uint16_t picParamSetLength = it->mLength;
27343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[0] = picParamSetLength >> 8;
27353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header[1] = picParamSetLength & 0xff;
27363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong
27373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        // PPS Nal unit (picture parameter set length bytes)
27383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        memcpy(&header[2], it->mData, picParamSetLength);
27393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong        header += (2 + picParamSetLength);
27403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong    }
274103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
274203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber    return OK;
274303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber}
274403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber
27459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData(
27479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size, HevcParameterSets &paramSets) {
27489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ALOGV("parseHEVCCodecSpecificData");
27509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *tmp = data;
27519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const uint8_t *nextStartCode = data;
27529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t bytesLeft = size;
27539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
275447d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar        nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4);
27559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4);
27569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (err != OK) {
27579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
27589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
27599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Move on to find the next parameter set
27619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        bytesLeft -= nextStartCode - tmp;
27629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        tmp = nextStartCode;
27639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
27649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t csdSize = 23;
27669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const size_t numNalUnits = paramSets.getNumNalUnits();
27679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) {
27689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kMandatoryHevcNalUnitTypes[i];
27699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
27709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets == 0) {
27719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Cound not find NAL unit of type %d", type);
27729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
27739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
27749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
27759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
27769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        int type = kHevcNalUnitTypes[i];
27779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numParamSets = paramSets.getNumNalUnitsOfType(type);
27789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numParamSets > 0xffff) {
27799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Too many seq parameter sets (%zu) found", numParamSets);
27809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
27819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
27829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        csdSize += 3;
27839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (size_t j = 0; j < numNalUnits; ++j) {
27849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (paramSets.getType(j) != type) {
27859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                continue;
27869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
27879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            csdSize += 2 + paramSets.getSize(j);
27889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
27899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
27909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificDataSize = csdSize;
27919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
27929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
27939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData(
27959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t *data, size_t size) {
27969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
27979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData != NULL) {
27989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Already have codec specific data");
27999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
28009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
28019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
28029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < 4) {
28039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Codec specific data length too short: %zu", size);
28049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
28059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
28069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
28079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Data is in the form of HEVCCodecSpecificData
28089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (memcmp("\x00\x00\x00\x01", data, 4)) {
28099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return copyHEVCCodecSpecificData(data, size);
28109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
28119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
28129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    HevcParameterSets paramSets;
28139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) {
28143d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed parsing codec specific data");
28159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
28169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
28179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
28189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mCodecSpecificData = malloc(mCodecSpecificDataSize);
28199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (mCodecSpecificData == NULL) {
28209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        mCodecSpecificDataSize = 0;
28219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("Failed allocating codec specific data");
28229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
28239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
28249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData,
28253d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim            &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2);
28269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (err != OK) {
28273d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim        ALOGE("failed constructing HVCC atom");
28289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return err;
28299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
28309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
28319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
28329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
28339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
2834872a481558350634a3fd5cb67939de288af00ecbJames Dong/*
2835872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that
2836872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information
2837872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio
2838872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger
2839872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
2840872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined.
2841872a481558350634a3fd5cb67939de288af00ecbJames Dong */
2842872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
2843872a481558350634a3fd5cb67939de288af00ecbJames Dong    int64_t driftTimeUs = 0;
2844872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
2845872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
2846872a481558350634a3fd5cb67939de288af00ecbJames Dong        int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
2847872a481558350634a3fd5cb67939de288af00ecbJames Dong        mOwner->setDriftTimeUs(timeUs);
2848872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
2849872a481558350634a3fd5cb67939de288af00ecbJames Dong}
2850872a481558350634a3fd5cb67939de288af00ecbJames Dong
285162a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuangvoid MPEG4Writer::Track::dumpTimeStamps() {
2852dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    ALOGE("Dumping %s track's last 10 frames timestamp and frame type ", getTrackType());
285362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    std::string timeStampString;
2854dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang    for (std::list<TimestampDebugHelperEntry>::iterator entry = mTimestampDebugHelper.begin();
2855dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang            entry != mTimestampDebugHelper.end(); ++entry) {
2856dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang        timeStampString += "(" + std::to_string(entry->pts)+
2857dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang                "us, " + std::to_string(entry->dts) + "us " + entry->frameType + ") ";
285862a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    }
285962a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang    ALOGE("%s", timeStampString.c_str());
286062a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang}
286162a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang
286237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() {
286330ab66297501757d745b9ae10da61adcd891f497Andreas Huber    int32_t count = 0;
286413aec890216948b0c364f8f92792129d0335f506James Dong    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
286543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    const bool hasMultipleTracks = (mOwner->numTracks() > 1);
286613aec890216948b0c364f8f92792129d0335f506James Dong    int64_t chunkTimestampUs = 0;
286713aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nChunks = 0;
28687c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar    int32_t nActualFrames = 0;        // frames containing non-CSD data (non-0 length)
286913aec890216948b0c364f8f92792129d0335f506James Dong    int32_t nZeroLengthFrames = 0;
2870965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastTimestampUs = 0;      // Previous sample time stamp
2871965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationUs = 0;       // Between the previous two samples
2872965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t currDurationTicks = 0;    // Timescale based ticks
2873965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t lastDurationTicks = 0;    // Timescale based ticks
2874965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int32_t sampleCount = 1;          // Sample count in the current stts table entry
2875000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    uint32_t previousSampleSize = 0;  // Size of the previous sample
2876a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t previousPausedDurationUs = 0;
2877965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    int64_t timestampUs = 0;
2878000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t cttsOffsetTimeUs = 0;
2879000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
2880000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
288143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong    int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
2882c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    uint32_t lastSamplesPerChunk = 0;
2883e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
2884a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    if (mIsAudio) {
2885a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
288625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (mIsVideo) {
2887a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
288825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else {
288925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0);
2890a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong    }
2891de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
2892de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    if (mOwner->isRealTimeRecording()) {
2893de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
2894de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    }
2895985f838934510983d8a887461e98dca60a6e858fJames Dong
2896d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong    sp<MetaData> meta_data;
289720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
289893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    status_t err = OK;
28991889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    MediaBufferBase *buffer;
290025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *trackName = getTrackType();
290193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    while (!mDone && (err = mSource->read(&buffer)) == OK) {
290220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (buffer->range_length() == 0) {
290320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer->release();
290420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            buffer = NULL;
290513aec890216948b0c364f8f92792129d0335f506James Dong            ++nZeroLengthFrames;
290620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            continue;
290720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
290820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2909a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // If the codec specific data has not been received yet, delay pause.
2910a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // After the codec specific data is received, discard what we received
2911a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        // when the track is to be paused.
2912a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        if (mPaused && !mResumed) {
2913a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer->release();
2914a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            buffer = NULL;
2915a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            continue;
2916a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2917a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
291830ab66297501757d745b9ae10da61adcd891f497Andreas Huber        ++count;
291930ab66297501757d745b9ae10da61adcd891f497Andreas Huber
292003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber        int32_t isCodecConfig;
29213d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        if (buffer->meta_data().findInt32(kKeyIsCodecConfig, &isCodecConfig)
292203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber                && isCodecConfig) {
29237c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // if config format (at track addition) already had CSD, keep that
29247c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // UNLESS we have not received any frames yet.
29257c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // TODO: for now the entire CSD has to come in one frame for encoders, even though
29267c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            // they need to be spread out for decoders.
29277c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            if (mGotAllCodecSpecificData && nActualFrames > 0) {
29287c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                ALOGI("ignoring additional CSD for video track after first frame");
29297c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar            } else {
29307c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                mMeta = mSource->getFormat(); // get output format after format change
29316e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                status_t err;
29327c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                if (mIsAvc) {
29336e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                    err = makeAVCCodecSpecificData(
29347c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
29357c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
29367c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
2937fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                } else if (mIsHevc || mIsHeic) {
29386e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                    err = makeHEVCCodecSpecificData(
29397c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            (const uint8_t *)buffer->data()
29407c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                                + buffer->range_offset(),
29417c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
29427c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                } else if (mIsMPEG4) {
29437c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                    copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
29447c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                            buffer->range_length());
29457c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar                }
294630ab66297501757d745b9ae10da61adcd891f497Andreas Huber            }
294730ab66297501757d745b9ae10da61adcd891f497Andreas Huber
294830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer->release();
294930ab66297501757d745b9ae10da61adcd891f497Andreas Huber            buffer = NULL;
29506e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang            if (OK != err) {
29516e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                mSource->stop();
29526e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
29536e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                       mTrackId | MEDIA_RECORDER_TRACK_ERROR_GENERAL, err);
29546e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang                break;
29556e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang            }
295630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
2957548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber            mGotAllCodecSpecificData = true;
295830ab66297501757d745b9ae10da61adcd891f497Andreas Huber            continue;
2959a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong        }
2960a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong
2961e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        // Per-frame metadata sample's size must be smaller than max allowed.
2962fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!mIsVideo && !mIsAudio && !mIsHeic &&
2963fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                buffer->range_length() >= kMaxMetadataSize) {
2964e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            ALOGW("Buffer size is %zu. Maximum metadata buffer size is %lld for %s track",
2965e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang                    buffer->range_length(), (long long)kMaxMetadataSize, trackName);
2966e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            buffer->release();
2967e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            mSource->stop();
2968e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            mIsMalformed = true;
2969e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang            break;
2970e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang        }
2971e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang
297299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        bool isExif = false;
297399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        int32_t isMuxerData;
297499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        if (buffer->meta_data().findInt32(kKeyIsMuxerData, &isMuxerData) && isMuxerData) {
297599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            // We only support one type of muxer data, which is Exif data block.
297699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            isExif = isExifData(buffer);
297799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            if (!isExif) {
297899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                ALOGW("Ignoring bad Exif data block");
297999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                buffer->release();
298099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                buffer = NULL;
298199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                continue;
298299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            }
298399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        }
298499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
29857c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar        ++nActualFrames;
29867c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar
2987d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // Make a deep copy of the MediaBuffer and Metadata and release
2988d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        // the original as soon as we can
2989d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
2990d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
2991d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong                buffer->range_length());
2992d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        copy->set_range(0, buffer->range_length());
29933d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        meta_data = new MetaData(buffer->meta_data());
2994d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer->release();
2995d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        buffer = NULL;
2996d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
299799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        if (isExif) {
299899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            copy->meta_data().setInt32(kKeyIsExif, 1);
299999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        }
300099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        bool usePrefix = this->usePrefix() && !isExif;
300199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
300299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        if (usePrefix) StripStartcode(copy);
3003e136c3bb38e88315bf8797a464ebf2c788296b22James Dong
3004b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        size_t sampleSize = copy->range_length();
300599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        if (usePrefix) {
3006b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            if (mOwner->useNalLengthFour()) {
3007b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 4;
3008b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            } else {
3009b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong                sampleSize += 2;
3010b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong            }
3011b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong        }
3012050b28a593350047845a45a14cc5026221ac1620James Dong
3013d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        // Max file size or duration handling
30141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        mMdatSizeBytes += sampleSize;
30151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong        updateTrackSizeEstimate();
30161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong
3017d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileSizeLimit()) {
3018fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            if (mOwner->switchFd() != OK) {
3019fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
3020fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        mOwner->mMaxFileSizeLimitBytes);
3021fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                mSource->stop();
3022fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                mOwner->notify(
3023fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
3024fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            } else {
3025fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                ALOGV("%s Current recorded file size exceeds limit %" PRId64 "bytes. Switching output",
3026fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang                        getTrackType(), mOwner->mMaxFileSizeLimitBytes);
3027fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            }
3028d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
3029d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
3030d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
3031fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang
3032d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        if (mOwner->exceedsFileDurationLimit()) {
3033316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang            ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
3034316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang                    mOwner->mMaxFileDurationLimitUs);
3035d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
3036d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            copy->release();
3037d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang            mSource->stop();
3038d599cd4573b5a2d5914c5040e0565ef866749b77James Dong            break;
3039d599cd4573b5a2d5914c5040e0565ef866749b77James Dong        }
3040d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
3041fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mOwner->approachingFileSizeLimit()) {
3042fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mOwner->notifyApproachingLimit();
3043fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
3044050b28a593350047845a45a14cc5026221ac1620James Dong
3045d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        int32_t isSync = false;
3046d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
3047d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
3048d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
3049fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        // For video, skip the first several non-key frames until getting the first key frame.
3050fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mIsVideo && !mGotStartKeyFrame && !isSync) {
3051fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            ALOGD("Video skip non-key frame");
3052fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            copy->release();
3053fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            continue;
3054fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
3055fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        if (mIsVideo && isSync) {
3056fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang            mGotStartKeyFrame = true;
3057fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang        }
3058d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong////////////////////////////////////////////////////////////////////////////////
305948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber
3060a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang        if (!mIsHeic) {
3061a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mStszTableEntries->count() == 0) {
3062a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mFirstSampleTimeRealUs = systemTime() / 1000;
3063a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mStartTimestampUs = timestampUs;
3064a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mOwner->setStartTimestampUs(mStartTimestampUs);
3065a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                previousPausedDurationUs = mStartTimestampUs;
306611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
306711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
3068a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mResumed) {
3069a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
3070a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
3071a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    copy->release();
3072a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mSource->stop();
3073a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mIsMalformed = true;
3074a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    break;
3075a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3076a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3077a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
3078a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
3079a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    copy->release();
3080a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mSource->stop();
3081a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mIsMalformed = true;
3082a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    break;
3083a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3084a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3085a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                previousPausedDurationUs += pausedDurationUs - lastDurationUs;
3086a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mResumed = false;
3087a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            }
3088a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            TimestampDebugHelperEntry timestampDebugEntry;
3089a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            timestampUs -= previousPausedDurationUs;
3090a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            timestampDebugEntry.pts = timestampUs;
3091a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
309211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
3093d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
30949db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
30959db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
309611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
309711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
3098a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mIsVideo) {
3099a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                /*
3100a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                 * Composition time: timestampUs
3101a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                 * Decoding time: decodingTimeUs
3102a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                 * Composition time offset = composition time - decoding time
3103a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                 */
3104a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                int64_t decodingTimeUs;
3105a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
3106a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                decodingTimeUs -= previousPausedDurationUs;
3107a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3108a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                // ensure non-negative, monotonic decoding time
3109a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mLastDecodingTimeUs < 0) {
3110a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    decodingTimeUs = std::max((int64_t)0, decodingTimeUs);
3111a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                } else {
3112a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // increase decoding time by at least the larger vaule of 1 tick and
3113a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // 0.1 milliseconds. This needs to take into account the possible
3114a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // delta adjustment in DurationTicks in below.
3115a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    decodingTimeUs = std::max(mLastDecodingTimeUs +
3116a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                            std::max(100, divUp(1000000, mTimeScale)), decodingTimeUs);
3117a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
311811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
3119a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mLastDecodingTimeUs = decodingTimeUs;
3120a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                timestampDebugEntry.dts = decodingTimeUs;
3121a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                timestampDebugEntry.frameType = isSync ? "Key frame" : "Non-Key frame";
3122a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                // Insert the timestamp into the mTimestampDebugHelper
3123a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mTimestampDebugHelper.size() >= kTimestampDebugCount) {
3124a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mTimestampDebugHelper.pop_front();
3125a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3126a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mTimestampDebugHelper.push_back(timestampDebugEntry);
3127a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3128a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                cttsOffsetTimeUs =
3129a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
3130a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
3131a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    copy->release();
3132a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mSource->stop();
3133a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mIsMalformed = true;
3134a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    break;
3135a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3136a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3137a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                timestampUs = decodingTimeUs;
3138a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64,
3139a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    timestampUs, cttsOffsetTimeUs);
3140a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3141a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                // Update ctts box table if necessary
3142a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                currCttsOffsetTimeTicks =
3143a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
3144a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
3145a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    copy->release();
3146a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mSource->stop();
3147a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mIsMalformed = true;
3148a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    break;
3149a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3150a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3151a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mStszTableEntries->count() == 0) {
3152a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // Force the first ctts table entry to have one single entry
3153a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // so that we can do adjustment for the initial track start
3154a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // time offset easily in writeCttsBox().
3155a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
3156a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
3157a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    cttsSampleCount = 0;      // No sample in ctts box is pending
3158a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                } else {
3159a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
3160a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
3161a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
3162a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        cttsSampleCount = 1;  // One sample in ctts box is pending
3163a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    } else {
3164a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        ++cttsSampleCount;
3165a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    }
3166a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3167a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3168a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                // Update ctts time offset range
3169a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mStszTableEntries->count() == 0) {
3170a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mMinCttsOffsetTicks = currCttsOffsetTimeTicks;
3171a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mMaxCttsOffsetTicks = currCttsOffsetTimeTicks;
3172a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                } else {
3173a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    if (currCttsOffsetTimeTicks > mMaxCttsOffsetTicks) {
3174a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        mMaxCttsOffsetTicks = currCttsOffsetTimeTicks;
3175a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTicks) {
3176a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        mMinCttsOffsetTicks = currCttsOffsetTimeTicks;
3177a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        mMinCttsOffsetTimeUs = cttsOffsetTimeUs;
3178a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    }
3179a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3180826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar            }
3181826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar
3182a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mOwner->isRealTimeRecording()) {
3183a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mIsAudio) {
3184a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    updateDriftTime(meta_data);
3185a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3186dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang            }
3187dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang
3188a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
318911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
3190d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
31919db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
31929db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
319311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
319411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
3195a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64,
3196a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    trackName, timestampUs, previousPausedDurationUs);
3197a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (timestampUs > mTrackDurationUs) {
3198a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                mTrackDurationUs = timestampUs;
3199a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            }
3200000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
3201a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // We need to use the time scale based ticks, rather than the
3202a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // timestamp itself to determine whether we have to use a new
3203a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // stts entry, since we may have rounding errors.
3204a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // The calculation is intended to reduce the accumulated
3205a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // rounding errors.
3206a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            currDurationTicks =
3207a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
3208a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
3209a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (currDurationTicks < 0ll) {
3210a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
3211a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        (long long)timestampUs, (long long)lastTimestampUs, trackName);
321211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih                copy->release();
3213d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang                mSource->stop();
32149db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                mIsMalformed = true;
32159db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang                break;
321611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            }
321711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih
3218a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // if the duration is different for this sample, see if it is close enough to the previous
3219a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // duration that we can fudge it and use the same value, to avoid filling the stts table
3220a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // with lots of near-identical entries.
3221a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // "close enough" here means that the current duration needs to be adjusted by less
3222a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            // than 0.1 milliseconds
3223a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
3224a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
3225a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                        + (mTimeScale / 2)) / mTimeScale;
3226a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (deltaUs > -100 && deltaUs < 100) {
3227a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // use previous ticks, and adjust timestamp as if it was actually that number
3228a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    // of ticks
3229a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    currDurationTicks = lastDurationTicks;
3230a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    timestampUs += deltaUs;
323143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong                }
323243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong            }
3233a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            mStszTableEntries->add(htonl(sampleSize));
3234a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mStszTableEntries->count() > 2) {
3235a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3236a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                // Force the first sample to have its own stts entry so that
3237a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                // we can adjust its value later to maintain the A/V sync.
3238a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
3239a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    addOneSttsTableEntry(sampleCount, lastDurationTicks);
3240a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    sampleCount = 1;
3241a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                } else {
3242a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    ++sampleCount;
3243000e18370baae60ffd9f25b509501dd8c26deabfJames Dong                }
32448c460498c028888c533ab442be12b6d4b669b965James Dong
324585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen            }
3246a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mSamplesHaveSameSize) {
3247a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
3248a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mSamplesHaveSameSize = false;
3249a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3250a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                previousSampleSize = sampleSize;
3251be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
3252a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64,
3253a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    trackName, timestampUs, lastTimestampUs);
3254a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            lastDurationUs = timestampUs - lastTimestampUs;
3255a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            lastDurationTicks = currDurationTicks;
3256a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            lastTimestampUs = timestampUs;
3257a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang
3258a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (isSync != 0) {
3259a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                addOneStssTableEntry(mStszTableEntries->count());
3260be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong            }
3261d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong
3262a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            if (mTrackingProgressStatus) {
3263a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                if (mPreviousTrackTimeUs <= 0) {
3264a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                    mPreviousTrackTimeUs = mStartTimestampUs;
3265a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                }
3266a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang                trackProgressStatus(timestampUs);
326793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong            }
326893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        }
326943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        if (!hasMultipleTracks) {
3270fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            size_t bytesWritten;
327199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            off64_t offset = mOwner->addSample_l(copy, usePrefix, isExif, &bytesWritten);
3272c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
3273fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (mIsHeic) {
327499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                addItemOffsetAndSize(offset, bytesWritten, isExif);
3275fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            } else {
3276fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                uint32_t count = (mOwner->use32BitFileOffset()
3277fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                            ? mStcoTableEntries->count()
3278fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                            : mCo64TableEntries->count());
3279c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
3280fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                if (count == 0) {
3281fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                    addChunkOffset(offset);
3282fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                }
328358ae9c530247668f8af36e30d228c716c226b3d4James Dong            }
328458ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy->release();
328558ae9c530247668f8af36e30d228c716c226b3d4James Dong            copy = NULL;
328658ae9c530247668f8af36e30d228c716c226b3d4James Dong            continue;
328758ae9c530247668f8af36e30d228c716c226b3d4James Dong        }
328813aec890216948b0c364f8f92792129d0335f506James Dong
328913aec890216948b0c364f8f92792129d0335f506James Dong        mChunkSamples.push_back(copy);
3290fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mIsHeic) {
3291fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            bufferChunk(0 /*timestampUs*/);
3292fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            ++nChunks;
3293fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else if (interleaveDurationUs == 0) {
32941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong            addOneStscTableEntry(++nChunks, 1);
32951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong            bufferChunk(timestampUs);
329613aec890216948b0c364f8f92792129d0335f506James Dong        } else {
329713aec890216948b0c364f8f92792129d0335f506James Dong            if (chunkTimestampUs == 0) {
329813aec890216948b0c364f8f92792129d0335f506James Dong                chunkTimestampUs = timestampUs;
329913aec890216948b0c364f8f92792129d0335f506James Dong            } else {
330043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
330143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                if (chunkDurationUs > interleaveDurationUs) {
330243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    if (chunkDurationUs > mMaxChunkDurationUs) {
330343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                        mMaxChunkDurationUs = chunkDurationUs;
330443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    }
330513aec890216948b0c364f8f92792129d0335f506James Dong                    ++nChunks;
330613aec890216948b0c364f8f92792129d0335f506James Dong                    if (nChunks == 1 ||  // First chunk
3307c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk != mChunkSamples.size()) {
3308c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        lastSamplesPerChunk = mChunkSamples.size();
3309c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                        addOneStscTableEntry(nChunks, lastSamplesPerChunk);
331013aec890216948b0c364f8f92792129d0335f506James Dong                    }
33111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong                    bufferChunk(timestampUs);
331213aec890216948b0c364f8f92792129d0335f506James Dong                    chunkTimestampUs = timestampUs;
331313aec890216948b0c364f8f92792129d0335f506James Dong                }
331413aec890216948b0c364f8f92792129d0335f506James Dong            }
331513aec890216948b0c364f8f92792129d0335f506James Dong        }
331613aec890216948b0c364f8f92792129d0335f506James Dong
331720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
331825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
331945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (isTrackMalFormed()) {
332062a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang        dumpTimeStamps();
3321690f546b0ee548dbfe997df36418e5302ec2d786James Dong        err = ERROR_MALFORMED;
3322f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong    }
332345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
3324bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    mOwner->trackProgressStatus(mTrackId, -1, err);
3325be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong
3326fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mIsHeic) {
3327fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!mChunkSamples.empty()) {
3328fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            bufferChunk(0);
3329fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            ++nChunks;
3330fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
3331be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong    } else {
3332fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // Last chunk
3333fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!hasMultipleTracks) {
3334fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            addOneStscTableEntry(1, mStszTableEntries->count());
3335fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else if (!mChunkSamples.empty()) {
3336fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            addOneStscTableEntry(++nChunks, mChunkSamples.size());
3337fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            bufferChunk(timestampUs);
3338fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
3339a472613aec322e25891abf5c77bf3f7e3c244920James Dong
3340fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // We don't really know how long the last frame lasts, since
3341fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // there is no frame time after it, just repeat the previous
3342fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // frame's duration.
3343fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mStszTableEntries->count() == 1) {
3344fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            lastDurationUs = 0;  // A single sample's duration
3345fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            lastDurationTicks = 0;
3346fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else {
3347fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            ++sampleCount;  // Count for the last sample
3348fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
3349fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
3350fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mStszTableEntries->count() <= 2) {
3351fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            addOneSttsTableEntry(1, lastDurationTicks);
3352fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (sampleCount - 1 > 0) {
3353fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
3354fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
3355fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else {
3356fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            addOneSttsTableEntry(sampleCount, lastDurationTicks);
3357a472613aec322e25891abf5c77bf3f7e3c244920James Dong        }
3358a472613aec322e25891abf5c77bf3f7e3c244920James Dong
3359fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // The last ctts box may not have been written yet, and this
3360fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        // is to make sure that we write out the last ctts box.
3361fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
3362fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (cttsSampleCount > 0) {
3363fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
3364fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
336543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        }
336643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong
3367fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        mTrackDurationUs += lastDurationUs;
3368fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
336925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber    mReachedEOS = true;
337043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
337143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    sendTrackSummary(hasMultipleTracks);
337243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
3373df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
337411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih            count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
3375872a481558350634a3fd5cb67939de288af00ecbJames Dong    if (mIsAudio) {
3376a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
3377872a481558350634a3fd5cb67939de288af00ecbJames Dong    }
3378365a963142093a1cd8efdcea76b5f65096a5b115James Dong
337937187916a486504acaf83bea30147eb5fbf46ae5James Dong    if (err == ERROR_END_OF_STREAM) {
338037187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
338137187916a486504acaf83bea30147eb5fbf46ae5James Dong    }
338237187916a486504acaf83bea30147eb5fbf46ae5James Dong    return err;
3383365a963142093a1cd8efdcea76b5f65096a5b115James Dong}
3384365a963142093a1cd8efdcea76b5f65096a5b115James Dong
338545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const {
33869db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    if (mIsMalformed) {
33879db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang        return true;
33889db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang    }
33899db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang
3390fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (!mIsHeic && mStszTableEntries->count() == 0) {  // no samples written
339129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("The number of recorded samples is 0");
339245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
339345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
339445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
339525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo && mStssTableEntries->count() == 0) {  // no sync frames for video
339629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("There are no sync frames for video track");
339745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
339845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
339945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
340045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    if (OK != checkCodecSpecificData()) {         // no codec specific data
340145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong        return true;
340245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    }
340345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
340445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong    return false;
340545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong}
340645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong
340743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
340807ec01904613a0bac32caaa8444b4690998faed7James Dong
340907ec01904613a0bac32caaa8444b4690998faed7James Dong    // Send track summary only if test mode is enabled.
341007ec01904613a0bac32caaa8444b4690998faed7James Dong    if (!isTestModeEnabled()) {
341107ec01904613a0bac32caaa8444b4690998faed7James Dong        return;
341207ec01904613a0bac32caaa8444b4690998faed7James Dong    }
341307ec01904613a0bac32caaa8444b4690998faed7James Dong
341443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    int trackNum = (mTrackId << 28);
341543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
341643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
341743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
341825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                    mIsAudio ? 0: 1);
341943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
342043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
342143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
342243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mTrackDurationUs / 1000);
342343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
342443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
342543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
3426c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong                    mStszTableEntries->count());
342743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
342886b7f47aa7482424cf8fd248f1315311919be3b0James Dong    {
342986b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // The system delay time excluding the requested initial delay that
343086b7f47aa7482424cf8fd248f1315311919be3b0James Dong        // is used to eliminate the recording sound.
343186b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
343286b7f47aa7482424cf8fd248f1315311919be3b0James Dong        if (startTimeOffsetUs < 0) {  // Start time offset was not set
343386b7f47aa7482424cf8fd248f1315311919be3b0James Dong            startTimeOffsetUs = kInitialDelayTimeUs;
343486b7f47aa7482424cf8fd248f1315311919be3b0James Dong        }
343586b7f47aa7482424cf8fd248f1315311919be3b0James Dong        int64_t initialDelayUs =
343686b7f47aa7482424cf8fd248f1315311919be3b0James Dong            mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
343786b7f47aa7482424cf8fd248f1315311919be3b0James Dong
343886b7f47aa7482424cf8fd248f1315311919be3b0James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
343970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
344070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    (initialDelayUs) / 1000);
344186b7f47aa7482424cf8fd248f1315311919be3b0James Dong    }
344270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
344307ec01904613a0bac32caaa8444b4690998faed7James Dong    mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
344407ec01904613a0bac32caaa8444b4690998faed7James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
344507ec01904613a0bac32caaa8444b4690998faed7James Dong                    mMdatSizeBytes / 1024);
344607ec01904613a0bac32caaa8444b4690998faed7James Dong
344743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    if (hasMultipleTracks) {
344843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong        mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
344943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
345043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong                    mMaxChunkDurationUs / 1000);
345170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong
345270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
345370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        if (mStartTimestampUs != moovStartTimeUs) {
345470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
345570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong            mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
345670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
345770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong                    startTimeOffsetUs / 1000);
345870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong        }
345943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong    }
346043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong}
346143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong
3462faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
3463a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("trackProgressStatus: %" PRId64 " us", timeUs);
3464c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong
3465215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong    if (mTrackEveryTimeDurationUs > 0 &&
3466215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
3467a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
3468bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
346993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong        mPreviousTrackTimeUs = timeUs;
347093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong    }
347193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong}
347293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong
3473faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus(
3474bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        size_t trackId, int64_t timeUs, status_t err) {
3475faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    Mutex::Autolock lock(mLock);
3476bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong    int32_t trackNum = (trackId << 28);
3477faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3478faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Error notification
3479faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    // Do not consider ERROR_END_OF_STREAM an error
3480faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (err != OK && err != ERROR_END_OF_STREAM) {
3481bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
3482bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
3483faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
3484faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        return;
3485faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
3486faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3487faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    if (timeUs == -1) {
3488faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send completion notification
3489bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
3490bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
3491faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               err);
3492faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    } else {
3493faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong        // Send progress status
3494bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
3495bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
3496faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong               timeUs / 1000);
3497faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong    }
3498faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong}
3499faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong
3500d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
3501a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs);
3502e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
3503d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mDriftTimeUs = driftTimeUs;
3504e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
3505e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
3506e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() {
3507a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs);
3508e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    Mutex::Autolock autolock(mLock);
3509e259531ce59ab1f31de5a23124b22536f6a5a767James Dong    return mDriftTimeUs;
3510e259531ce59ab1f31de5a23124b22536f6a5a767James Dong}
3511e259531ce59ab1f31de5a23124b22536f6a5a767James Dong
3512de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const {
3513de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui    return mIsRealTimeRecording;
3514de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui}
3515de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui
3516b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() {
3517b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong    return mUse4ByteNalLength;
3518b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong}
3519b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong
35201c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
35213856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("bufferChunk");
35221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong
35231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    Chunk chunk(this, timestampUs, mChunkSamples);
35241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong    mOwner->bufferChunk(chunk);
352513aec890216948b0c364f8f92792129d0335f506James Dong    mChunkSamples.clear();
352620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
352720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35283b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const {
3529230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    return mTrackDurationUs + getStartTimeOffsetTimeUs();
353020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
353120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3532d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
3533d599cd4573b5a2d5914c5040e0565ef866749b77James Dong    return mEstimatedTrackSizeBytes;
3534d599cd4573b5a2d5914c5040e0565ef866749b77James Dong}
3535d599cd4573b5a2d5914c5040e0565ef866749b77James Dong
353699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhangint32_t MPEG4Writer::Track::getMetaSizeIncrease(
353799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        int32_t angle, int32_t trackCount) const {
3538fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    CHECK(mIsHeic);
353956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
354099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    int32_t grid = (mTileWidth > 0);
354199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    int32_t rotate = (angle > 0);
354256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
354356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // Note that the rotation angle is in the file meta, and we don't have
354456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // it until start, so here the calculation has to assume rotation.
354556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
354656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // increase to ipco
354756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    int32_t increase = 20 * (grid + 1)              // 'ispe' property
354856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                     + (8 + mCodecSpecificDataSize) // 'hvcC' property
354999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                     ;
355099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
355199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    if (rotate) {
355299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        increase += 9;                              // 'irot' property (worst case)
355399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    }
355456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
355556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    // increase to iref and idat
355656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    if (grid) {
355799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        increase += (12 + mNumTiles * 2)            // 'dimg' in iref
355899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                  + 12;                             // ImageGrid in 'idat' (worst case)
355956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    }
356056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
356199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    increase += (12 + 2);                           // 'cdsc' in iref
356256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
356399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    // increase to iloc, iinf
356499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    increase += (16                                 // increase to 'iloc'
356599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang              + 21)                                 // increase to 'iinf'
356699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang              * (mNumTiles + grid + 1);             // "+1" is for 'Exif'
356799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
356899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    // When total # of properties is > 127, the properties id becomes 2-byte.
356999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    // We write 4 properties at most for each image (2x'ispe', 1x'hvcC', 1x'irot').
357099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    // Set the threshold to be 30.
357199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    int32_t propBytes = trackCount > 30 ? 2 : 1;
357299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
357399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    // increase to ipma
357499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    increase += (3 + 2 * propBytes) * mNumTiles     // 'ispe' + 'hvcC'
357599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang             + grid * (3 + propBytes)               // 'ispe' for grid
357699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang             + rotate * propBytes;                  // 'irot' (either on grid or tile)
357756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang
357856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang    return increase;
3579fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
3580fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
3581690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const {
3582690f546b0ee548dbfe997df36418e5302ec2d786James Dong    const char *mime;
3583690f546b0ee548dbfe997df36418e5302ec2d786James Dong    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
3584690f546b0ee548dbfe997df36418e5302ec2d786James Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
3585690f546b0ee548dbfe997df36418e5302ec2d786James Dong        !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
35869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
3587fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime) ||
3588fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        !strcasecmp(MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, mime)) {
3589690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (!mCodecSpecificData ||
3590690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize <= 0) {
359129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Missing codec specific data");
3592690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
3593690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
3594690f546b0ee548dbfe997df36418e5302ec2d786James Dong    } else {
3595690f546b0ee548dbfe997df36418e5302ec2d786James Dong        if (mCodecSpecificData ||
3596690f546b0ee548dbfe997df36418e5302ec2d786James Dong            mCodecSpecificDataSize > 0) {
359729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Unexepected codec specific data found");
3598690f546b0ee548dbfe997df36418e5302ec2d786James Dong            return ERROR_MALFORMED;
3599690f546b0ee548dbfe997df36418e5302ec2d786James Dong        }
3600690f546b0ee548dbfe997df36418e5302ec2d786James Dong    }
3601690f546b0ee548dbfe997df36418e5302ec2d786James Dong    return OK;
3602690f546b0ee548dbfe997df36418e5302ec2d786James Dong}
3603690f546b0ee548dbfe997df36418e5302ec2d786James Dong
360425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangconst char *MPEG4Writer::Track::getTrackType() const {
3605fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    return mIsAudio ? "Audio" :
3606fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang           mIsVideo ? "Video" :
3607fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang           mIsHeic  ? "Image" :
3608fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                      "Metadata";
360925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
36108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong
361125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
3612efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson    uint32_t now = getMpeg4Time();
3613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("trak");
3614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeTkhdBox(now);
3615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->beginBox("mdia");
3616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeMdhdBox(now);
3617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            writeHdlrBox();
3618b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->beginBox("minf");
3619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                if (mIsAudio) {
3620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeSmhdBox();
362125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                } else if (mIsVideo) {
3622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                    writeVmhdBox();
362325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                } else {
362425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang                    writeNmhdBox();
3625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                }
3626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeDinfBox();
3627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong                writeStblBox(use32BitOffset);
3628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong            mOwner->endBox();  // minf
3629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->endBox();  // mdia
3630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // trak
3631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3633230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuangint64_t MPEG4Writer::Track::getMinCttsOffsetTimeUs() {
3634230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // For video tracks with ctts table, this should return the minimum ctts
3635230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // offset in the table. For non-video tracks or video tracks without ctts
3636230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    // table, this will return kMaxCttsOffsetTimeUs.
3637230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
3638230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        return kMaxCttsOffsetTimeUs;
3639230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    }
3640230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    return mMinCttsOffsetTimeUs;
3641230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang}
3642230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang
3643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
3644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stbl");
3645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsd");
3646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);               // version=0, flags=0
3647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);               // entry count
3648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (mIsAudio) {
3649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAudioFourCCBox();
365025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else if (mIsVideo) {
3651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeVideoFourCCBox();
365225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    } else {
365325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        writeMetadataFourCCBox();
3654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsd
3656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeSttsBox();
365725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (mIsVideo) {
365825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        writeCttsBox();
3659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeStssBox();
3660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3661b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStszBox();
3662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStscBox();
3663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeStcoBox(use32BitOffset);
3664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stbl
3665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
366725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeMetadataFourCCBox() {
366825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *mime;
366925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    bool success = mMeta->findCString(kKeyMIMEType, &mime);
367025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    CHECK(success);
367125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    const char *fourcc = getFourCCForMime(mime);
367225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (fourcc == NULL) {
367325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        ALOGE("Unknown mime type '%s'.", mime);
367425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
367525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    }
367625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->beginBox(fourcc);    // TextMetaDataSampleEntry
367725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeCString(mime);  // metadata mime_format
367825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->endBox(); // mett
367925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
368025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
3681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() {
3682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
36858b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
36868b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
368729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
368825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
3689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
36918b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    mOwner->beginBox(fourcc);        // video format
3692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // data ref index
3695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3698b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // predefined
3700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t width, height;
3702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeyWidth, &width);
3703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = success && mMeta->findInt32(kKeyHeight, &height);
3704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(width);
3707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(height);
3708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // horiz resolution
3709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x480000);    // vert resolution
3710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(1);           // frame count
3712c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->writeInt8(0);            // compressor string length
3713c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo    mOwner->write("                               ", 31);
3714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x18);        // depth
3715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(-1);          // predefined
3716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
3718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4vEsdsBox();
3719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
3720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeD263Box();
3721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
3722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeAvccBox();
37239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
37249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        writeHvccBox();
3725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writePaspBox();
372858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    writeColrBox();
3729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // mp4v, s263 or avc1
3730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
373258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() {
373358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    ColorAspects aspects;
373458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    memset(&aspects, 0, sizeof(aspects));
373558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    // TRICKY: using | instead of || because we want to execute all findInt32-s
373658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
373758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
373858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
373958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
374058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t primaries, transfer, coeffs;
374158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        bool fullRange;
374258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorUtils::convertCodecColorAspectsToIsoAspects(
374358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                aspects, &primaries, &transfer, &coeffs, &fullRange);
374458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->beginBox("colr");
374558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeFourcc("nclx");
374658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(primaries);
374758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(transfer);
374858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->writeInt16(coeffs);
3749fffb0c8fbe16ac948619b85e1eea9e65a9daa0c9Pirama Arumuga Nainar        mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0));
375058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        mOwner->endBox(); // colr
375158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
375258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar}
375358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
3754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() {
3755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    const char *mime;
3756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    bool success = mMeta->findCString(kKeyMIMEType, &mime);
3757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
37588b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    const char *fourcc = getFourCCForMime(mime);
37598b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan    if (fourcc == NULL) {
376029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown mime type '%s'.", mime);
376125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang        TRESPASS();
3762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(fourcc);        // audio format
3765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x1);         // data ref index
3768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // reserved
3770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t nChannels;
3771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
3772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(nChannels);   // channel count
3773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(16);          // sample size
3774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // predefined
3775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t samplerate;
3778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    success = mMeta->findInt32(kKeySampleRate, &samplerate);
3779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(success);
3780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(samplerate << 16);
3781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
3782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeMp4aEsdsBox();
3783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
3784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong               !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
3785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        writeDamrBox();
3786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() {
3791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
3793b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GT(mCodecSpecificDataSize, 0u);
3794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Make sure all sizes encode to a single byte.
3796b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_LT(mCodecSpecificDataSize + 23, 128u);
3797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);     // version=0, flags=0
3799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);   // ES_DescrTag
3800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);// ES_ID
3802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x00);
3803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
3805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
3807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x15);   // streamType AudioStream
3808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x03);  // XXX
381046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt8(0x00);   // buffer size 24-bit (0x300)
381146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
381296bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
381346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
381496bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
381546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
381646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
381746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
3818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
3820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() {
3834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
3835b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GT(mCodecSpecificDataSize, 0u);
3836bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3837bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan    // Make sure all sizes encode to a single byte.
3838b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_LT(23 + mCodecSpecificDataSize, 128u);
3839bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan
3840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("esds");
3841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);    // version=0, flags=0
3843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x03);  // ES_DescrTag
3845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(23 + mCodecSpecificDataSize);
3846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x0000);  // ES_ID
3847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x1f);
3848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
3850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(15 + mCodecSpecificDataSize);
3851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
3852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x11);  // streamType VisualStream
3853b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData[] = {
385546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        0x01, 0x77, 0x00, // buffer size 96000 bytes
3856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData, sizeof(kData));
3858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
385996bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t avgBitrate = 0;
386046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
386196bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar    int32_t maxBitrate = 0;
386246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
386346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(maxBitrate);
386446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar    mOwner->writeInt32(avgBitrate);
386546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
3866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
3867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(mCodecSpecificDataSize);
3869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
3870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    static const uint8_t kData2[] = {
3872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x06,  // SLConfigDescriptorTag
3873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x01,
3874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        0x02
3875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    };
3876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(kData2, sizeof(kData2));
3877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // esds
3879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3881efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) {
3882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("tkhd");
3883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Flags = 7 to indicate that the track is enabled, and
3884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // part of the presentation
3885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x07);          // version=0, flags=7
3886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // creation time
3887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(now);           // modification time
3888219f195159f93d627af2b243732e3f9020511a46James Dong    mOwner->writeInt32(mTrackId);      // track id starts with 1
3889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
38908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong    int64_t trakDurationUs = getDurationUs();
3891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t mvhdTimeScale = mOwner->getTimeScale();
3892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int32_t tkhdDuration =
3893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
3894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
3895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // layer
3898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // alternate group
3899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
3900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // reserved
3901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCompositionMatrix(mRotation);       // matrix
390320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
390425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    if (!mIsVideo) {
3905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(0);
3907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    } else {
3908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        int32_t width, height;
3909467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        bool success = mMeta->findInt32(kKeyDisplayWidth, &width);
3910467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        success = success && mMeta->findInt32(kKeyDisplayHeight, &height);
3911467743d462773ada299148ed5a210479affd1f4cHangyu Kuang
3912467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        // Use width/height if display width/height are not present.
3913467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        if (!success) {
3914467743d462773ada299148ed5a210479affd1f4cHangyu Kuang            success = mMeta->findInt32(kKeyWidth, &width);
3915467743d462773ada299148ed5a210479affd1f4cHangyu Kuang            success = success && mMeta->findInt32(kKeyHeight, &height);
3916467743d462773ada299148ed5a210479affd1f4cHangyu Kuang        }
3917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        CHECK(success);
3918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
3920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
3921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
3922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // tkhd
3923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() {
3926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("vmhd");
3927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0x01);        // version=0, flags=1
3928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // graphics mode
3929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // opcolor
3930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);
3932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() {
3936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("smhd");
3937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);           // version=0, flags=0
3938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // balance
3939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);           // reserved
3940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
394325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeNmhdBox() {
394425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->beginBox("nmhd");
394525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeInt32(0);           // version=0, flags=0
394625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->endBox();
394725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang}
394825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang
3949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() {
3950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("hdlr");
3951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // version=0, flags=0
3952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // component type: should be mhlr
395325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeFourcc(mIsAudio ? "soun" : (mIsVideo ? "vide" : "meta"));  // component subtype
3954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);             // reserved
3957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Removing "r" for the name string just makes the string 4 byte aligned
395825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang    mOwner->writeCString(mIsAudio ? "SoundHandle": (mIsVideo ? "VideoHandle" : "MetadHandle"));
3959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3962efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
3963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t trakDurationUs = getDurationUs();
39641d515f4b608f1e6592780365857855962c0da725xiahong.bao    int64_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
3965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("mdhd");
39661d515f4b608f1e6592780365857855962c0da725xiahong.bao
39671d515f4b608f1e6592780365857855962c0da725xiahong.bao    if (mdhdDuration > UINT32_MAX) {
39681d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32((1 << 24));            // version=1, flags=0
39691d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt64((int64_t)now);         // creation time
39701d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt64((int64_t)now);         // modification time
39711d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(mTimeScale);           // media timescale
39721d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt64(mdhdDuration);         // media timescale
39731d515f4b608f1e6592780365857855962c0da725xiahong.bao    } else {
39741d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(0);                      // version=0, flags=0
39751d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(now);                    // creation time
39761d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(now);                    // modification time
39771d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32(mTimeScale);             // media timescale
39781d515f4b608f1e6592780365857855962c0da725xiahong.bao        mOwner->writeInt32((int32_t)mdhdDuration);  // use media timescale
39791d515f4b608f1e6592780365857855962c0da725xiahong.bao    }
3980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Language follows the three letter standard ISO-639-2/T
3981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 'e', 'n', 'g' for "English", for instance.
3982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Each character is packed as the difference between its ASCII value and 0x60.
3983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // For "English", these are 00101, 01110, 00111.
3984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // XXX: Where is the padding bit located: 0x15C7?
3985decc50efede28c5d73137c30d1a95d72dd405555David Yeh    const char *lang = NULL;
3986decc50efede28c5d73137c30d1a95d72dd405555David Yeh    int16_t langCode = 0;
3987decc50efede28c5d73137c30d1a95d72dd405555David Yeh    if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) {
3988decc50efede28c5d73137c30d1a95d72dd405555David Yeh        langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f);
3989decc50efede28c5d73137c30d1a95d72dd405555David Yeh    }
3990decc50efede28c5d73137c30d1a95d72dd405555David Yeh    mOwner->writeInt16(langCode);      // language code
3991b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0);             // predefined
3992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
3993b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
3994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
3995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() {
3996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // 3gpp2 Spec AMRSampleEntry fields
3997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("damr");
3998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeCString("   ");  // vendor: 4 bytes
3999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // decoder version
4000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt16(0x83FF);   // mode set: all enabled
4001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);         // mode change period
4002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(1);         // frames per sample
4003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();
4004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
4005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
4006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() {
4007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // The table index here refers to the sample description index
4008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // in the sample table entries.
4009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("url ");
4010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
4011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // url
4012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
4013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
4014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() {
4015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dref");
4016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
4017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1);  // entry count (either url or urn)
4018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeUrlBox();
4019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dref
4020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
4021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
4022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() {
4023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("dinf");
4024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    writeDrefBox();
4025b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // dinf
4026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
4027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
4028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() {
4029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    CHECK(mCodecSpecificData);
4030b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GE(mCodecSpecificDataSize, 5u);
4031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
4032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // Patch avcc's lengthSize field to match the number
4033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    // of bytes we use to indicate the size of a nal unit.
4034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
4035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
4036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("avcC");
4037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
4038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // avcC
4039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
4040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
40419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
40429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() {
40439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK(mCodecSpecificData);
4044b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_GE(mCodecSpecificDataSize, 5u);
40459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
40469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Patch avcc's lengthSize field to match the number
40479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // of bytes we use to indicate the size of a nal unit.
40489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t *ptr = (uint8_t *)mCodecSpecificData;
40499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
40509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->beginBox("hvcC");
40519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
40529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mOwner->endBox();  // hvcC
40539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
40549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
4055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() {
4056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("d263");
4057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // vendor
4058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // decoder version
4059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(10);  // level: 10
4060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt8(0);   // profile: 0
4061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // d263
4062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
4063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
4064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square
4065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() {
4066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("pasp");
4067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // hspacing
4068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(1 << 16);  // vspacing
4069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // pasp
4070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
4071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong
4072230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuangint64_t MPEG4Writer::Track::getStartTimeOffsetTimeUs() const {
4073a472613aec322e25891abf5c77bf3f7e3c244920James Dong    int64_t trackStartTimeOffsetUs = 0;
4074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
4075a9292fe1c19e8a9b43398ba3d69284c215d7589fRobert Shih    if (mStartTimestampUs != -1 && mStartTimestampUs != moovStartTimeUs) {
407643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong        CHECK_GT(mStartTimestampUs, moovStartTimeUs);
4077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong        trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
4078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
40796a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih    return trackStartTimeOffsetUs;
40806a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih}
40816a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih
40826a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shihint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
4083230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    return (getStartTimeOffsetTimeUs() * mTimeScale + 500000LL) / 1000000LL;
4084000e18370baae60ffd9f25b509501dd8c26deabfJames Dong}
4085000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
4086000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() {
4087000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->beginBox("stts");
4088000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
4089230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
4090230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // For non-vdeio tracks or video tracks without ctts table,
4091230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // adjust duration of first sample for tracks to account for
4092230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // first sample not starting at the media start time.
4093230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // TODO: consider signaling this using some offset
4094230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        // as this is not quite correct.
4095230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        uint32_t duration;
4096230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        CHECK(mSttsTableEntries->get(duration, 1));
4097230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        duration = htonl(duration);  // Back to host byte order
4098230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang        mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
4099230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    }
4100c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mSttsTableEntries->write(mOwner);
4101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stts
4102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
410320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4104965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() {
4105000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    // There is no B frame at all
4106230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
4107000e18370baae60ffd9f25b509501dd8c26deabfJames Dong        return;
4108000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    }
4109000e18370baae60ffd9f25b509501dd8c26deabfJames Dong
4110965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    // Do not write ctts box when there is no need to have it.
4111c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (mCttsTableEntries->count() == 0) {
4112965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong        return;
4113965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    }
4114965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
4115a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
4116230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang            mCttsTableEntries->count(), mMinCttsOffsetTicks, mMaxCttsOffsetTicks);
4117965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
4118965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->beginBox("ctts");
4119000e18370baae60ffd9f25b509501dd8c26deabfJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
4120230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t deltaTimeUs = kMaxCttsOffsetTimeUs - getStartTimeOffsetTimeUs();
4121230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang    int64_t delta = (deltaTimeUs * mTimeScale + 500000LL) / 1000000LL;
4122c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) {
4123c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        // entries are <count, ctts> pairs; adjust only ctts
4124c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar        uint32_t duration = htonl(value[1]); // back to host byte order
41250d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        // Prevent overflow and underflow
41260d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        if (delta > duration) {
41270d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka            duration = 0;
41280d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        } else if (delta < 0 && UINT32_MAX + delta < duration) {
41290d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka            duration = UINT32_MAX;
41300d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        } else {
41310d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka            duration -= delta;
41320d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        }
41330d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka        value[1] = htonl(duration);
4134c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar    });
4135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mCttsTableEntries->write(mOwner);
4136965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong    mOwner->endBox();  // ctts
4137965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong}
4138965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong
4139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() {
4140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stss");
4141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
4142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStssTableEntries->write(mOwner);
4143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stss
4144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
414525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber
4146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() {
4147b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsz");
4148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
4149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mOwner->writeInt32(0);
4150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStszTableEntries->write(mOwner);
4151b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsz
4152b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
415320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4154b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() {
4155b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox("stsc");
4156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
4157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    mStscTableEntries->write(mOwner);
4158b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stsc
4159b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong}
416020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
4162b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->beginBox(use32BitOffset? "stco": "co64");
4163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->writeInt32(0);  // version=0, flags=0
4164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    if (use32BitOffset) {
4165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mStcoTableEntries->write(mOwner);
4166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong    } else {
4167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong        mCo64TableEntries->write(mOwner);
4168b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    }
4169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong    mOwner->endBox();  // stco or co64
417020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
417120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
417207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() {
417307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("udta");
417407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeGeoDataBox();
417507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
417607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
417707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
4178fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeHdlr(const char *handlerType) {
4179e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("hdlr");
4180e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Version, Flags
4181e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Predefined
4182fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeFourcc(handlerType);
4183e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[0]
4184e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[1]
4185e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0); // Reserved[2]
4186e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt8(0);  // Name (empty)
4187e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
4188e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
4189e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4190e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() {
4191e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
4192e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4193e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("keys");
4194e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(0);     // Version, Flags
4195e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeInt32(count); // Entry_count
4196e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
4197e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
4198e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
4199e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        size_t n = strlen(key);
4200e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeInt32(n + 8);
4201e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        writeFourcc("mdta");
4202e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        write(key, n); // write without the \0
4203e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
4204e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
4205e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
4206e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4207e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() {
4208e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
4209e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4210e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("ilst");
4211e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    for (size_t i = 0; i < count; i++) {
4212e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox(i + 1); // key id (1-based)
4213e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        beginBox("data");
4214e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        AMessage::Type type;
4215e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        const char *key = mMetaKeys->getEntryNameAt(i, &type);
4216e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        switch (type) {
42177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            case AMessage::kTypeString:
42187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            {
42197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                AString val;
42207c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                CHECK(mMetaKeys->findString(key, &val));
42217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(1); // type = UTF8
42227c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0); // default country/language
42237c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                write(val.c_str(), strlen(val.c_str())); // write without \0
42247c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                break;
42257c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang            }
42267c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang
4227e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeFloat:
4228e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
4229e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                float val;
4230e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findFloat(key, &val));
42317c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(23); // type = float32
42327c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
4233e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(*reinterpret_cast<int32_t *>(&val));
4234e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
4235e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
4236e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4237e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            case AMessage::kTypeInt32:
4238e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
4239e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                int32_t val;
4240e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                CHECK(mMetaKeys->findInt32(key, &val));
42417c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(67); // type = signed int32
42427c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
4243e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(val);
4244e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
4245e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
4246e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4247e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            default:
4248e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            {
4249e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                ALOGW("Unsupported key type, writing 0 instead");
42507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(77); // type = unsigned int32
42517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang                writeInt32(0);  // default country/language
4252e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                writeInt32(0);
4253e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang                break;
4254e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang            }
4255e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        }
4256e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // data
4257e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        endBox(); // key id
4258e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
4259e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox(); // ilst
4260e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
4261e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4262fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeMoovLevelMetaBox() {
4263e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    size_t count = mMetaKeys->countEntries();
4264e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    if (count == 0) {
4265e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang        return;
4266e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    }
4267e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4268e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    beginBox("meta");
4269fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeHdlr("mdta");
4270e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeKeys();
4271e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    writeIlst();
4272e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang    endBox();
4273e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang}
4274e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang
4275fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIlocBox() {
4276fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("iloc");
4277fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // Use version 1 to allow construction method 1 that refers to
4278fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // data in idat box inside meta box.
4279fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(0x01000000); // Version = 1, Flags = 0
4280fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt16(0x4400);     // offset_size = length_size = 4
4281fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                            // base_offset_size = index_size = 0
4282fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4283fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // 16-bit item_count
4284fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    size_t itemCount = mItems.size();
4285fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (itemCount > 65535) {
4286fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGW("Dropping excess items: itemCount %zu", itemCount);
4287fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        itemCount = 65535;
4288fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4289fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt16((uint16_t)itemCount);
4290fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4291fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (size_t i = 0; i < itemCount; i++) {
4292fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInt16(mItems[i].itemId);
4293fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        bool isGrid = mItems[i].isGrid();
4294fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4295fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInt16(isGrid ? 1 : 0); // construction_method
4296fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInt16(0); // data_reference_index = 0
4297fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInt16(1); // extent_count = 1
4298fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4299fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (isGrid) {
4300fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            // offset into the 'idat' box
4301fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt32(mNumGrids++ * 8);
4302fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt32(8);
4303fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        } else {
4304fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt32(mItems[i].offset);
4305fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt32(mItems[i].size);
4306fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4307fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4308fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4309fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4310fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4311fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeInfeBox(
4312fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        uint16_t itemId, const char *itemType, uint32_t flags) {
4313fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("infe");
4314fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(0x02000000 | flags); // Version = 2, Flags = 0
4315fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt16(itemId);
4316fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt16(0);          //item_protection_index = 0
4317fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeFourcc(itemType);
4318fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeCString("");       // item_name
4319fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4320fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4321fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4322fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIinfBox() {
4323fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("iinf");
4324fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(0);          // Version = 0, Flags = 0
4325fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4326fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // 16-bit item_count
4327fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    size_t itemCount = mItems.size();
4328fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (itemCount > 65535) {
4329fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGW("Dropping excess items: itemCount %zu", itemCount);
4330fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        itemCount = 65535;
4331fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4332fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4333fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt16((uint16_t)itemCount);
4334fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (size_t i = 0; i < itemCount; i++) {
4335fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInfeBox(mItems[i].itemId, mItems[i].itemType,
433699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                (mItems[i].isImage() && mItems[i].isHidden) ? 1 : 0);
4337fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4338fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4339fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4340fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4341fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4342fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIdatBox() {
4343fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("idat");
4344fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4345fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (size_t i = 0; i < mItems.size(); i++) {
4346fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mItems[i].isGrid()) {
4347fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt8(0); // version
4348fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            // flags == 1 means 32-bit width,height
4349fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            int8_t flags = (mItems[i].width > 65535 || mItems[i].height > 65535);
4350fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt8(flags);
4351fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt8(mItems[i].rows - 1);
4352fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            writeInt8(mItems[i].cols - 1);
4353fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (flags) {
4354fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt32(mItems[i].width);
4355fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt32(mItems[i].height);
4356fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            } else {
4357fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt16((uint16_t)mItems[i].width);
4358fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt16((uint16_t)mItems[i].height);
4359fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
4360fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4361fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4362fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4363fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4364fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4365fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4366fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIrefBox() {
4367fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("iref");
4368fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(0);          // Version = 0, Flags = 0
4369fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    {
4370fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        for (size_t i = 0; i < mItems.size(); i++) {
437199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            for (size_t r = 0; r < mItems[i].refsList.size(); r++) {
437299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                const ItemRefs &refs = mItems[i].refsList[r];
437399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                beginBox(refs.key);
437499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                writeInt16(mItems[i].itemId);
437599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                size_t refCount = refs.value.size();
437699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                if (refCount > 65535) {
437799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                    ALOGW("too many entries in %s", refs.key);
437899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                    refCount = 65535;
437999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                }
438099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                writeInt16((uint16_t)refCount);
438199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                for (size_t refIndex = 0; refIndex < refCount; refIndex++) {
438299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                    writeInt16(refs.value[refIndex]);
438399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                }
438499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang                endBox();
4385fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
4386fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4387fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4388fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4389fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4390fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4391fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writePitmBox() {
4392fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("pitm");
4393fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(0);          // Version = 0, Flags = 0
4394fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt16(mPrimaryItemId);
4395fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4396fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4397fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4398fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIpcoBox() {
4399fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("ipco");
4400fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    size_t numProperties = mProperties.size();
4401fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (numProperties > 32767) {
4402fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGW("Dropping excess properties: numProperties %zu", numProperties);
4403fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        numProperties = 32767;
4404fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4405fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (size_t propIndex = 0; propIndex < numProperties; propIndex++) {
440656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang        switch (mProperties[propIndex].type) {
440756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            case FOURCC('h', 'v', 'c', 'C'):
440856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            {
440956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                beginBox("hvcC");
441056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                sp<ABuffer> hvcc = mProperties[propIndex].hvcc;
441156eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                // Patch avcc's lengthSize field to match the number
441256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                // of bytes we use to indicate the size of a nal unit.
441356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                uint8_t *ptr = (uint8_t *)hvcc->data();
441456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                ptr[21] = (ptr[21] & 0xfc) | (useNalLengthFour() ? 3 : 1);
441556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                write(hvcc->data(), hvcc->size());
441656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                endBox();
441756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                break;
441856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            }
441956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            case FOURCC('i', 's', 'p', 'e'):
442056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            {
442156eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                beginBox("ispe");
442256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                writeInt32(0); // Version = 0, Flags = 0
442356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                writeInt32(mProperties[propIndex].width);
442456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                writeInt32(mProperties[propIndex].height);
442556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                endBox();
442656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                break;
442756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            }
442856eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            case FOURCC('i', 'r', 'o', 't'):
442956eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            {
443056eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                beginBox("irot");
443156eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                writeInt8(mProperties[propIndex].rotation);
443256eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                endBox();
443356eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                break;
443456eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            }
443556eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang            default:
443656eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                ALOGW("Skipping unrecognized property: type 0x%08x",
443756eab8ec67058fe06d6014c56600021e2b965c9eChong Zhang                        mProperties[propIndex].type);
4438fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4439fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4440fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4441fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4442fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4443fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIpmaBox() {
4444fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("ipma");
4445fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    uint32_t flags = (mProperties.size() > 127) ? 1 : 0;
4446fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(flags); // Version = 0
4447fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4448fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(mAssociationEntryCount);
4449fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (size_t itemIndex = 0; itemIndex < mItems.size(); itemIndex++) {
4450fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        const Vector<uint16_t> &properties = mItems[itemIndex].properties;
4451fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (properties.empty()) {
4452fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            continue;
4453fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4454fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInt16(mItems[itemIndex].itemId);
4455fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4456fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        size_t entryCount = properties.size();
4457fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (entryCount > 255) {
4458fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            ALOGW("Dropping excess associations: entryCount %zu", entryCount);
4459fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            entryCount = 255;
4460fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4461fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeInt8((uint8_t)entryCount);
4462fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        for (size_t propIndex = 0; propIndex < entryCount; propIndex++) {
4463fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (flags & 1) {
4464fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt16((1 << 15) | properties[propIndex]);
4465fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            } else {
4466fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                writeInt8((1 << 7) | properties[propIndex]);
4467fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
4468fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4469fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4470fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4471fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4472fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4473fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIprpBox() {
4474fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("iprp");
4475fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeIpcoBox();
4476fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeIpmaBox();
4477fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4478fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4479fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4480fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeFileLevelMetaBox() {
4481fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // patch up the mPrimaryItemId and count items with prop associations
4482a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang    uint16_t firstVisibleItemId = 0;
448399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    uint16_t firstImageItemId = 0;
4484fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    for (size_t index = 0; index < mItems.size(); index++) {
448599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        if (!mItems[index].isImage()) continue;
448699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
4487fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (mItems[index].isPrimary) {
4488fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mPrimaryItemId = mItems[index].itemId;
448999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        }
449099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        if (!firstImageItemId) {
449199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            firstImageItemId = mItems[index].itemId;
449299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        }
449399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        if (!firstVisibleItemId && !mItems[index].isHidden) {
4494a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            firstVisibleItemId = mItems[index].itemId;
4495fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4496fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        if (!mItems[index].properties.empty()) {
4497fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            mAssociationEntryCount++;
4498fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4499fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4500fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
450199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    if (!firstImageItemId) {
450299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        ALOGE("no valid image was found");
450399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        return;
450499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    }
450599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
4506fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mPrimaryItemId == 0) {
4507a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang        if (firstVisibleItemId > 0) {
450899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            ALOGW("didn't find primary, using first visible image");
4509a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang            mPrimaryItemId = firstVisibleItemId;
4510a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang        } else {
451199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            ALOGW("no primary and no visible item, using first image");
451299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            mPrimaryItemId = firstImageItemId;
451399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        }
451499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    }
451599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
451699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    for (List<Track *>::iterator it = mTracks.begin();
451799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        it != mTracks.end(); ++it) {
451899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        if ((*it)->isHeic()) {
451999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang            (*it)->flushItemRefs();
4520a4d7b69074e5d7584bff2bbbfe4205979006f1ffChong Zhang        }
4521fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4522fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4523fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    beginBox("meta");
4524fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeInt32(0); // Version = 0, Flags = 0
4525fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeHdlr("pict");
4526fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeIlocBox();
4527fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeIinfBox();
4528fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writePitmBox();
4529fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    writeIprpBox();
4530fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (mNumGrids > 0) {
4531fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeIdatBox();
453299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    }
453399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    if (mHasRefs) {
4534fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        writeIrefBox();
4535fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4536fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    endBox();
4537fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4538fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4539fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhanguint16_t MPEG4Writer::addProperty_l(const ItemProperty &prop) {
4540fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    char typeStr[5];
4541fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    MakeFourCCString(prop.type, typeStr);
4542fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    ALOGV("addProperty_l: %s", typeStr);
4543fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4544fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mProperties.push_back(prop);
4545fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4546fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    // returning 1-based property index
4547fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    return mProperties.size();
4548fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4549fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4550fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhanguint16_t MPEG4Writer::addItem_l(const ItemInfo &info) {
4551fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    ALOGV("addItem_l: type %s, offset %u, size %u",
4552fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            info.itemType, info.offset, info.size);
4553fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4554fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    size_t index = mItems.size();
4555fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    mItems.push_back(info);
4556fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
455799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    // make the item id start at kItemIdBase
455899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    mItems.editItemAt(index).itemId = index + kItemIdBase;
4559fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4560fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang#if (LOG_NDEBUG==0)
4561fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    if (!info.properties.empty()) {
4562fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        AString str;
4563fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        for (size_t i = 0; i < info.properties.size(); i++) {
4564fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            if (i > 0) {
4565fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang                str.append(", ");
4566fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            }
4567fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang            str.append(info.properties[i]);
4568fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        }
4569fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang        ALOGV("addItem_l: id %d, properties: %s", mItems[index].itemId, str.c_str());
4570fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    }
4571fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang#endif // (LOG_NDEBUG==0)
4572fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
4573fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang    return mItems[index].itemId;
4574fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang}
4575fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang
457699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhangvoid MPEG4Writer::addRefs_l(uint16_t itemId, const ItemRefs &refs) {
457799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    if (refs.value.empty()) {
457899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        return;
457999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    }
458099745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    if (itemId < kItemIdBase) {
458199745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        ALOGW("itemId shouldn't be smaller than kItemIdBase");
458299745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang        return;
458399745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    }
458499745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
458599745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    size_t index = itemId - kItemIdBase;
458699745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    mItems.editItemAt(index).refsList.push_back(refs);
458799745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang    mHasRefs = true;
458899745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang}
458999745d1c3017e9ac25f8bb2c91cc47bb432d5248Chong Zhang
459007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/*
459107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard.
459207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */
459307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() {
459407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    beginBox("\xA9xyz");
459507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    /*
459607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * For historical reasons, any user data start
459707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * with "\0xA9", must be followed by its assoicated
459807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     * language code.
4599432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x0012: text string length
4600432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong     * 0x15c7: lang (locale) code: en
460107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong     */
460207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt32(0x001215c7);
460307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLatitude(mLatitudex10000);
460407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeLongitude(mLongitudex10000);
460507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    writeInt8(0x2F);
460607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong    endBox();
460707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong}
460807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong
460920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
4610