MPEG4Writer.cpp revision fbc97c5266ec4e9fbe98db944f7aa99452299ae8
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/* 220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project 320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License. 620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at 720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software 1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and 1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License. 1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */ 1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0 18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "MPEG4Writer" 19050b28a593350047845a45a14cc5026221ac1620James Dong 20826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar#include <algorithm> 21826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar 2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h> 23a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <fcntl.h> 24a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h> 2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h> 26a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/prctl.h> 27a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/stat.h> 28a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/types.h> 29a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <unistd.h> 30a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn 31a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <utils/Log.h> 3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar#include <functional> 34c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar 35d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/MediaSource.h> 3643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong#include <media/stagefright/foundation/ADebug.h> 37e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang#include <media/stagefright/foundation/AMessage.h> 38826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar#include <media/stagefright/foundation/AUtils.h> 39607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang#include <media/stagefright/foundation/ByteUtils.h> 4058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar#include <media/stagefright/foundation/ColorUtils.h> 41d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/stagefright/foundation/avc_utils.h> 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 4518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 4603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h> 4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 48d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h> 4907ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h> 5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h" 529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include "include/HevcUtils.h" 53dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn 54dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false 55dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0) 56dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif 57dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn 5811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \ 59dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \ 6011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih ALOGW("Condition %s failed " message, #condition, ##__VA_ARGS__); \ 6111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih true; \ 6211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih})) 6311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6677e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024; 671f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32 681f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad // filesystem file size 691f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad // used by most SD cards 703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07; 713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08; 7270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs = 700000LL; 73e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuangstatic const int64_t kMaxMetadataSize = 0x4000000LL; // 64MB max per-frame metadata size 745b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong 757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[] = "com.android.version"; 76da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuangstatic const char kMetaKey_Manufacturer[] = "com.android.manufacturer"; 773b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[] = "com.android.model"; 78da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang 79da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang#ifdef SHOW_BUILD 807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[] = "com.android.build"; 813b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif 827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps"; 834dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatic const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count"; 847c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 8562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuangstatic const int kTimestampDebugCount = 10; 8662a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang 879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = { 889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeVps, 899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeSps, 909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypePps, 919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}; 929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = { 939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeVps, 949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeSps, 959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypePps, 969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypePrefixSei, 979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeSuffixSei, 989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}; 99da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang/* uncomment to include build in meta */ 1007c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1 1017c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 104ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kang Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId); 1058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 109fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang status_t stop(bool stopSource = true); 11037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 11125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1133b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 114d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 115fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int32_t getMetaSizeIncrease() const; 116b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTrackHeader(bool use32BitOffset = true); 117230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang int64_t getMinCttsOffsetTimeUs(); 1181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 1191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 1209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bool isHevc() const { return mIsHevc; } 121fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang bool isHeic() const { return mIsHeic; } 1221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 1231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 124fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang bool usePrefix() const { return mIsAvc || mIsHevc || mIsHeic; } 125c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong void addChunkOffset(off64_t offset); 126fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang void addItemOffsetAndSize(off64_t offset, size_t size); 12770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int32_t getTrackId() const { return mTrackId; } 128dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 1298b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan static const char *getFourCCForMime(const char *mime); 13025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *getTrackType() const; 131fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang void resetInternal(); 13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 134000e18370baae60ffd9f25b509501dd8c26deabfJames Dong enum { 13505f4cd73b9655a6d4aad9fa215d6fc13c40633aaZhijun He kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 1368c460498c028888c533ab442be12b6d4b669b965James Dong kSampleArraySize = 1000, 137000e18370baae60ffd9f25b509501dd8c26deabfJames Dong }; 138000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // A helper class to handle faster write box with table entries 140c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar template<class TYPE, unsigned ENTRY_SIZE> 141c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar // ENTRY_SIZE: # of values in each entry 142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong struct ListTableEntries { 143c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar static_assert(ENTRY_SIZE > 0, "ENTRY_SIZE must be positive"); 144c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries(uint32_t elementCapacity) 145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mElementCapacity(elementCapacity), 146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTotalNumTableEntries(0), 147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry(0), 148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement(NULL) { 149b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_GT(mElementCapacity, 0u); 1502177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia // Ensure no integer overflow on allocation in add(). 151c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar CHECK_LT(ENTRY_SIZE, UINT32_MAX / mElementCapacity); 152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Free the allocated memory. 155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ~ListTableEntries() { 156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (!mTableEntryList.empty()) { 157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete[] (*it); 159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.erase(it); 160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Replace the value at the given position by the given value. 164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // There must be an existing value at the given position. 165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order 166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void set(const TYPE& value, uint32_t pos) { 168c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar CHECK_LT(pos, mTotalNumTableEntries * ENTRY_SIZE); 169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 171c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE)); 172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 177b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_EQ(iterations, 0u); 178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 179c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar (*it)[(pos % (mElementCapacity * ENTRY_SIZE))] = value; 180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Get the value at the given position by the given value. 183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value the retrieved value at the position in network byte order. 184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @return true if a value is found. 186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool get(TYPE& value, uint32_t pos) const { 187c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar if (pos >= mTotalNumTableEntries * ENTRY_SIZE) { 188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return false; 189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 192c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE)); 193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 198b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_EQ(iterations, 0u); 199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 200c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar value = (*it)[(pos % (mElementCapacity * ENTRY_SIZE))]; 201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return true; 202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 204c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar // adjusts all values by |adjust(value)| 205c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar void adjustEntries( 206c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar std::function<void(size_t /* ix */, TYPE(& /* entry */)[ENTRY_SIZE])> update) { 207c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar size_t nEntries = mTotalNumTableEntries + mNumValuesInCurrEntry / ENTRY_SIZE; 208c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar size_t ix = 0; 209c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar for (TYPE *entryArray : mTableEntryList) { 210c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar size_t num = std::min(nEntries, (size_t)mElementCapacity); 211c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar for (size_t i = 0; i < num; ++i) { 212c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar update(ix++, (TYPE(&)[ENTRY_SIZE])(*entryArray)); 213c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar entryArray += ENTRY_SIZE; 214c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar } 215c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar nEntries -= num; 216c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar } 217c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar } 218c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar 219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Store a single value. 220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order. 221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void add(const TYPE& value) { 222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 224c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t nValues = mNumValuesInCurrEntry % ENTRY_SIZE; 225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries == 0 && nValues == 0) { 226c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCurrTableEntriesElement = new TYPE[ENTRY_SIZE * mElementCapacity]; 227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCurrTableEntriesElement != NULL); 228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.push_back(mCurrTableEntriesElement); 229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 231c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t pos = nEntries * ENTRY_SIZE + nValues; 232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement[pos] = value; 233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mNumValuesInCurrEntry; 235c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar if ((mNumValuesInCurrEntry % ENTRY_SIZE) == 0) { 236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mTotalNumTableEntries; 237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry = 0; 238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Write out the table entries: 242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 1. the number of entries goes first 243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 2. followed by the values in the table enties in order 244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg writer the writer to actual write to the storage 245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void write(MPEG4Writer *writer) const { 246b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_EQ(mNumValuesInCurrEntry % ENTRY_SIZE, 0u); 247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries; 248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->writeInt32(nEntries); 249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong it != mTableEntryList.end(); ++it) { 251b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_GT(nEntries, 0u); 252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries >= mElementCapacity) { 253c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, mElementCapacity); 254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong nEntries -= mElementCapacity; 255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 256c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, nEntries); 257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong break; 258c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 261c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 262c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Return the number of entries in the table. 263c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count() const { return mTotalNumTableEntries; } 264c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 265c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong private: 266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mElementCapacity; // # entries in an element 267c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mTotalNumTableEntries; 268c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t mNumValuesInCurrEntry; // up to ENTRY_SIZE 269c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong TYPE *mCurrTableEntriesElement; 270c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mutable List<TYPE *> mTableEntryList; 271c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 272c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong }; 274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 276c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 279ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kang sp<MediaSource> mSource; 28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 281a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 282a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 283eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 2841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 2859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bool mIsHevc; 2861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 28725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang bool mIsVideo; 288fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang bool mIsHeic; 2891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 290fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang bool mGotStartKeyFrame; 2919db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang bool mIsMalformed; 292bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 293c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 29443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 295826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar int64_t mLastDecodingTimeUs; 296e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 297d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 2981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 2998f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 303be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 30413aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 3051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 306c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool mSamplesHaveSameSize; 307c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 1> *mStszTableEntries; 308be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 309c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 1> *mStcoTableEntries; 310c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<off64_t, 1> *mCo64TableEntries; 311c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 3> *mStscTableEntries; 312c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 1> *mStssTableEntries; 313c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 2> *mSttsTableEntries; 314c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 2> *mCttsTableEntries; 315965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 316000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMinCttsOffsetTimeUs; 317230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang int64_t mMinCttsOffsetTicks; 318230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang int64_t mMaxCttsOffsetTicks; 319965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 320dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang // Save the last 10 frames' timestamp and frame type for debug. 321dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang struct TimestampDebugHelperEntry { 322dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang int64_t pts; 323dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang int64_t dts; 324dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang std::string frameType; 325dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang }; 326dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang 327dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang std::list<TimestampDebugHelperEntry> mTimestampDebugHelper; 32862a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang 3293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 3303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 3313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 3323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 3333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 3343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 3353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 3363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 3373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 3383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 3393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 3403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 3413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 3423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 345548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 34693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 34825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 3493c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 35070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 35170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 35293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 35393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 35425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 355fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int32_t mRotation; 356fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 357fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang Vector<uint16_t> mProperties; 358fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang Vector<uint16_t> mDimgRefs; 359fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int32_t mIsPrimary; 360fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int32_t mWidth, mHeight; 361fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int32_t mGridWidth, mGridHeight; 362fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int32_t mGridRows, mGridCols; 363fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang size_t mNumTiles, mTileIndex; 364fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 365872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 366872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 367872a481558350634a3fd5cb67939de288af00ecbJames Dong 36862a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang void dumpTimeStamps(); 36962a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang 370230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang int64_t getStartTimeOffsetTimeUs() const; 371000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int32_t getStartTimeOffsetScaledTime() const; 372000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 37437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 3773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 3783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 3799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0); 3809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 384215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 3859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size); 3869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size); 3879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t parseHEVCCodecSpecificData( 3889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, HevcParameterSets ¶mSets); 3899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 390215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 391faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 39293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 39303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 39419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 39519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 396c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 397c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 398c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 399c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 400c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 401c059860c73678a202bfa33062723e8f82fb779d9James Dong 402690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 403690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 404690f546b0ee548dbfe997df36418e5302ec2d786James Dong 4051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 4061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 4071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 40879761ab096f57c3027fad9556c2bc436672d614eJames Dong 40979761ab096f57c3027fad9556c2bc436672d614eJames Dong // Duration is time scale based 41079761ab096f57c3027fad9556c2bc436672d614eJames Dong void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 411965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 41245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 41345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong bool isTrackMalFormed() const; 41443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 4151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 422965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void writeCttsBox(); 423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 4269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim void writeHvccBox(); 427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 429b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 430b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 431efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeMdhdBox(uint32_t now); 432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 433b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 43425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang void writeNmhdBox(); 435b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 436efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeTkhdBox(uint32_t now); 43758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar void writeColrBox(); 438b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 439b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 441b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 44225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang void writeMetadataFourCCBox(); 443b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 444b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 449fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu KuangMPEG4Writer::MPEG4Writer(int fd) { 4505ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang initInternal(fd, true /*isFirstSession*/); 45130ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 45230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 45320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 4548bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong reset(); 45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 4571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 4591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 4601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 463fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 464fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mNextFd != -1) { 465fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang close(mNextFd); 466fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 467fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 468fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 4695ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuangvoid MPEG4Writer::initInternal(int fd, bool isFirstSession) { 470fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGV("initInternal"); 4718fdb3fde346b446ad3b04dafa65a6844da672e23Hangyu Kuang mFd = dup(fd); 472fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mNextFd = -1; 473fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mInitCheck = mFd < 0? NO_INIT: OK; 4745ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang 4755ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mInterleaveDurationUs = 1000000; 4765ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang 4775ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mStartTimestampUs = -1ll; 4785ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mStartTimeOffsetMs = -1; 479fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mPaused = false; 480fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStarted = false; 481fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mWriterThreadStarted = false; 482fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSendNotify = false; 4835ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang 4845ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang // Reset following variables for all the sessions and they will be 4855ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang // initialized in start(MetaData *param). 4865ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mIsRealTimeRecording = true; 4875ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mUse4ByteNalLength = true; 4885ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mUse32BitOffset = true; 489fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mOffset = 0; 490fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMdatOffset = 0; 491fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMoovBoxBuffer = NULL; 492fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMoovBoxBufferOffset = 0; 493fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mWriteMoovBoxToMemory = false; 494fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mFreeBoxOffset = 0; 495fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStreamableFile = false; 496fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mEstimatedMoovBoxSize = 0; 497fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mTimeScale = -1; 498fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mHasFileLevelMeta = false; 499fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mHasMoovBox = false; 500fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mPrimaryItemId = 0; 501fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mAssociationEntryCount = 0; 502fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mNumGrids = 0; 5035ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang 5045ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang // Following variables only need to be set for the first recording session. 5055ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang // And they will stay the same for all the recording sessions. 5065ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang if (isFirstSession) { 5075ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mMoovExtraSize = 0; 5085ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mMetaKeys = new AMessage(); 5095ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang addDeviceMeta(); 5105ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mLatitudex10000 = 0; 5115ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mLongitudex10000 = 0; 5125ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mAreGeoTagsAvailable = false; 5135ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mSwitchPending = false; 5145ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang mIsFileSizeLimitExplicitlyRequested = false; 5155ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang } 5165ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang 517fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // Verify mFd is seekable 518fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang off64_t off = lseek64(mFd, 0, SEEK_SET); 519fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (off < 0) { 520fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGE("cannot seek mFd: %s (%d) %lld", strerror(errno), errno, (long long)mFd); 521fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang release(); 522fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 523fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang for (List<Track *>::iterator it = mTracks.begin(); 524fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang it != mTracks.end(); ++it) { 525fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang (*it)->resetInternal(); 526fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 529dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 530dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 531dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 532dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 533dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 534dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 535dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 536dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 537dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 538dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 539dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 540dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 541dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 542dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 543dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 544dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 545dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 546dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 54784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber int fd, const Vector<String16>& /* args */) const { 548dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 549dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 550dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 55125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang snprintf(buffer, SIZE, " %s track\n", getTrackType()); 552dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 553dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 554dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 555dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 556c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 55713210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 558377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); 55913210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 560dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 561dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 562dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 563dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 5648b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static 5658b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) { 5668b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (mime == NULL) { 5678b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 5688b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 5698b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strncasecmp(mime, "audio/", 6)) { 5708b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 5718b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "samr"; 5728b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 5738b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "sawb"; 5748b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 5758b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4a"; 5768b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 5778b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strncasecmp(mime, "video/", 6)) { 5788b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 5798b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4v"; 5808b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 5818b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "s263"; 5828b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 5838b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "avc1"; 5849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 5859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return "hvc1"; 5868b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 58725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (!strncasecmp(mime, "application/", 12)) { 58825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang return "mett"; 589fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else if (!strcasecmp(MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, mime)) { 590fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang return "heic"; 5918b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else { 59225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("Track (%s) other than video/audio/metadata is not supported", mime); 5938b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 5948b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 5958b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan} 5968b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan 597ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kangstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 598bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 599bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 60029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Attempt to add source AFTER recording is started"); 601bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 602bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 603acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 604acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong CHECK(source.get() != NULL); 605acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 606acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong const char *mime; 607acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong source->getFormat()->findCString(kKeyMIMEType, &mime); 608acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 60925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (Track::getFourCCForMime(mime) == NULL) { 61025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("Unsupported mime '%s'", mime); 61125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang return ERROR_UNSUPPORTED; 61225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } 61325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang 61425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang // This is a metadata track or the first track of either audio or video 615acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // Go ahead to add the track. 616219f195159f93d627af2b243732e3f9020511a46James Dong Track *track = new Track(this, source, 1 + mTracks.size()); 61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 6182dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 619fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mHasMoovBox |= !track->isHeic(); 620fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mHasFileLevelMeta |= track->isHeic(); 621fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 6222dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 626acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.empty()) { 627acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("No source added"); 628acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return INVALID_OPERATION; 629acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 630acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 631a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 632a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 63393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 634a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 635a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 636a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 637a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 638a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 639a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 640a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 641a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 642a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 643a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 644a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 645a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 646a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 6477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() { 6487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // add device info and estimate space in 'moov' 6497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang char val[PROPERTY_VALUE_MAX]; 6507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size_t n; 6517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // meta size is estimated by adding up the following: 6527c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - meta header structures, which occur only once (total 66 bytes) 6537c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - size for each key, which consists of a fixed header (32 bytes), 6547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // plus key length and data length. 6557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 66; 6567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.version.release", val, NULL) 6577c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 6587c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Version, val, n + 1); 6597c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32; 6607c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 661da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang 662da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang if (property_get_bool("media.recorder.show_manufacturer_and_model", false)) { 663da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang if (property_get("ro.product.manufacturer", val, NULL) 664da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang && (n = strlen(val)) > 0) { 665da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang mMetaKeys->setString(kMetaKey_Manufacturer, val, n + 1); 666da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang mMoovExtraSize += sizeof(kMetaKey_Manufacturer) + n + 32; 667da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang } 668da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang if (property_get("ro.product.model", val, NULL) 669da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang && (n = strlen(val)) > 0) { 670da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang mMetaKeys->setString(kMetaKey_Model, val, n + 1); 671da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32; 672da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang } 6737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 674da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang#ifdef SHOW_MODEL_BUILD 6757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.display.id", val, NULL) 6767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 6777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Build, val, n + 1); 6787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32; 6797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 6807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif 6817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang} 6827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 683fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangint64_t MPEG4Writer::estimateFileLevelMetaSize() { 684fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // base meta size 685fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int64_t metaSize = 12 // meta fullbox header 686fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + 33 // hdlr box 687fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + 14 // pitm box 688fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + 16 // iloc box (fixed size portion) 689fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + 14 // iinf box (fixed size portion) 690fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + 32 // iprp box (fixed size protion) 691fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + 8 // idat box (when empty) 692fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + 12 // iref box (when empty) 693fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ; 694fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 695fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang for (List<Track *>::iterator it = mTracks.begin(); 696fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang it != mTracks.end(); ++it) { 697fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if ((*it)->isHeic()) { 698fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang metaSize += (*it)->getMetaSizeIncrease(); 699fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 700fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 701fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 702fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGV("estimated meta size: %lld", (long long) metaSize); 703fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 704fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // Need at least 8-byte padding at the end, otherwise the left-over 705fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // freebox may become malformed 706fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang return metaSize + 8; 707fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 708fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 7092dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 7102dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 7112dec2b5be2056c6d9428897dc672185872d30d17James Dong // 7122dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 7132dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 7142dec2b5be2056c6d9428897dc672185872d30d17James Dong 71578a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 7162dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 71778a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 7182dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 7192dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 7202dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 7212dec2b5be2056c6d9428897dc672185872d30d17James Dong 7222dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 7232dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 7242dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 72578a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 7262dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 7272dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 7282dec2b5be2056c6d9428897dc672185872d30d17James Dong 72978a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 730a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 73178a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 73278a1a286f736888ae7af8860b2c424af0d978848James Dong } 73378a1a286f736888ae7af8860b2c424af0d978848James Dong 73478a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 73578a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 73678a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 73778a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 7380ca31521644b9396829850f7400d23f9b107cc64Johan Redestig ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000; 73978a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 74078a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 74178a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 74278a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 74378a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 74478a1a286f736888ae7af8860b2c424af0d978848James Dong } 74578a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 74678a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 74778a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 74878a1a286f736888ae7af8860b2c424af0d978848James Dong } 7492dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7502dec2b5be2056c6d9428897dc672185872d30d17James Dong } 75178a1a286f736888ae7af8860b2c424af0d978848James Dong 7522dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 7532dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 7542dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7552dec2b5be2056c6d9428897dc672185872d30d17James Dong 7562dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 7572dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 7582dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 7592dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 7602dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7612dec2b5be2056c6d9428897dc672185872d30d17James Dong 7627c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // Account for the extra stuff (Geo, meta keys, etc.) 7637c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size += mMoovExtraSize; 7647c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 765a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the" 766a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn " estimated moov size %" PRId64 " bytes", 7672dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 768fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 769fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int64_t estimatedSize = factor * size; 770fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang CHECK_GE(estimatedSize, 8); 771fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 772fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang return estimatedSize; 7732dec2b5be2056c6d9428897dc672185872d30d17James Dong} 7742dec2b5be2056c6d9428897dc672185872d30d17James Dong 7752dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 776674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 77725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 779fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStartMeta = param; 78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 781a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 782a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 783a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 784a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 785a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 786a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 787a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 788a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 789a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 790a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 7912dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 7922dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 7932dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 7942dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 7952dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 7962dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7972dec2b5be2056c6d9428897dc672185872d30d17James Dong 7981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 7991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 8001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 8011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 8021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 8031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 8051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 8061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 807a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. " 808a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn "It is changed to %" PRId64 " bytes", 809d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 810d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 8111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 8121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 8131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 814b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 815b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 816b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 817b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 818b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 8192dec2b5be2056c6d9428897dc672185872d30d17James Dong } 8202dec2b5be2056c6d9428897dc672185872d30d17James Dong 821de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui int32_t isRealTimeRecording; 822de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) { 823de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording = isRealTimeRecording; 824de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 825de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 826065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 82793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 828a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 829a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 830a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 83193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 832a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 833a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 834a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 835a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 8368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 8378f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 8388f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 8398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 84043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 8413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("movie time scale: %d", mTimeScale); 8428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 84377e8ae9967a078770416619e99ddb5b010def312James Dong /* 84477e8ae9967a078770416619e99ddb5b010def312James Dong * When the requested file size limit is small, the priority 84577e8ae9967a078770416619e99ddb5b010def312James Dong * is to meet the file size limit requirement, rather than 8467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to make the file streamable. mStreamableFile does not tell 8477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * whether the actual recorded file is streamable or not. 84877e8ae9967a078770416619e99ddb5b010def312James Dong */ 84977e8ae9967a078770416619e99ddb5b010def312James Dong mStreamableFile = 85077e8ae9967a078770416619e99ddb5b010def312James Dong (mMaxFileSizeLimitBytes != 0 && 85177e8ae9967a078770416619e99ddb5b010def312James Dong mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 85277e8ae9967a078770416619e99ddb5b010def312James Dong 8537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong /* 8547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory is true if the amount of data in moov box is 8557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * smaller than the reserved free space at the beginning of a file, AND 8567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * when the content of moov box is constructed. Note that video/audio 8577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * frame data is always written to the file but not in the memory. 8587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 8597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Before stop()/reset() is called, mWriteMoovBoxToMemory is always 8607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * false. When reset() is called at the end of a recording session, 8617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Moov box needs to be constructed. 8627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 8637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory 8647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to set to mStreamableFile so that if 8657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the file is intended to be streamable, it is set to true; 8667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * otherwise, it is set to false. When the value is set to false, 8677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * all the content of the moov box is written immediately to 8687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the end of the file. When the value is set to true, all the 8697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * content of the moov box is written to an in-memory cache, 8707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mMoovBoxBuffer, util the following condition happens. Note 8717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * that the size of the in-memory cache is the same as the 8727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * reserved free space at the beginning of the file. 8737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 8747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 2) While the data of the moov box is written to an in-memory 8757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache, the data size is checked against the reserved space. 8767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * If the data size surpasses the reserved space, subsequent moov 8777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * data could no longer be hold in the in-memory cache. This also 8787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * indicates that the reserved space was too small. At this point, 8797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * _all_ moov data must be written to the end of the file. 8807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory must be set to false to direct the write 8817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to the file. 8827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 8837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 3) If the data size in moov box is smaller than the reserved 8847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space after moov box is completely constructed, the in-memory 8857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache copy of the moov box is written to the reserved free 8867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space. Thus, immediately after the moov is completedly 8877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * constructed, mWriteMoovBoxToMemory is always set to false. 8887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong */ 8897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 8907837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 8917837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 8927837c17063a4c50bc856ba59418516fdab731de7James Dong 893fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 894fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGV("muxer starting: mHasMoovBox %d, mHasFileLevelMeta %d", 895fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mHasMoovBox, mHasFileLevelMeta); 896fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 89820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8997837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 90020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9017837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 9022dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 903fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mHasFileLevelMeta) { 904fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mEstimatedMoovBoxSize += estimateFileLevelMetaSize(); 905fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 906fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mHasMoovBox) { 907fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (param) { 908fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang param->findInt32(kKeyBitRate, &bitRate); 909fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 910fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mEstimatedMoovBoxSize += estimateMoovBoxSize(bitRate); 9112dec2b5be2056c6d9428897dc672185872d30d17James Dong } 9127837c17063a4c50bc856ba59418516fdab731de7James Dong } 91377e8ae9967a078770416619e99ddb5b010def312James Dong if (mStreamableFile) { 91477e8ae9967a078770416619e99ddb5b010def312James Dong // Reserve a 'free' box only for streamable file 91577e8ae9967a078770416619e99ddb5b010def312James Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 91677e8ae9967a078770416619e99ddb5b010def312James Dong writeInt32(mEstimatedMoovBoxSize); 91777e8ae9967a078770416619e99ddb5b010def312James Dong write("free", 4); 91877e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 91977e8ae9967a078770416619e99ddb5b010def312James Dong } else { 92077e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mOffset; 92177e8ae9967a078770416619e99ddb5b010def312James Dong } 9227837c17063a4c50bc856ba59418516fdab731de7James Dong 9237837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 924c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 9251acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 9261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 9271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 9281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 9291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 9301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 9321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 9331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 9341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 9351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 937a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 938a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 93920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 9401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 941a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 94225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 94420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 9461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 9471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 9481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 94937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 9505ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang ALOGW("MPEG4Writer: pause is not supported"); 9515ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang return ERROR_UNSUPPORTED; 952a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 953a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 9541c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 955b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping writer thread"); 956411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 957411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 958411ba422e3635d534928ffd81abf54f4f291c739James Dong } 9591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 9611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 9621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 9641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 9651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 9661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 9681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 969411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 970b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Writer thread stopped"); 9711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 9721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 97313f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 97413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 97513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 97613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 97713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 97813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 97913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 98013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 98113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 98213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 98313f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 98413f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 9853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeCompositionMatrix"); 98613f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 98713f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 98813f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 98913f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 99013f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 99113f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 99213f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 99313f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 99413f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 99513f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 99613f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 99713f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 99813f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 99913f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 100013f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 100113f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 100213f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 100313f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 100413f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 100513f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 100613f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 100713f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 100813f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 100913f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 101013f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 101113f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 101213f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 101313f6284305e4b27395a23db7882d670bdb1bcae1James Dong 101413f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 101513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 101613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 101713f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 101813f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 101913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 102013f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 102113f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 102213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 102313f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 102413f6284305e4b27395a23db7882d670bdb1bcae1James Dong 1025411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 1026411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 1027411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 1028411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 1029411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 10304c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary free(mMoovBoxBuffer); 10314c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary mMoovBoxBuffer = NULL; 1032411ba422e3635d534928ffd81abf54f4f291c739James Dong} 103313f6284305e4b27395a23db7882d670bdb1bcae1James Dong 1034fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::finishCurrentSession() { 1035fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang reset(false /* stopSource */); 1036fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1037fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1038fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::switchFd() { 1039fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGV("switchFd"); 1040fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang Mutex::Autolock l(mLock); 1041fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mSwitchPending) { 1042fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return OK; 1043fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1044fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1045fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mNextFd == -1) { 1046fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGW("No FileDescripter for next recording"); 1047fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return INVALID_OPERATION; 1048fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1049fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1050fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSwitchPending = true; 1051fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang sp<AMessage> msg = new AMessage(kWhatSwitch, mReflector); 1052fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang status_t err = msg->post(); 1053fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1054fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return err; 1055fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1056fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1057fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::reset(bool stopSource) { 1058674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 105937187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1060411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 1061411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 1062411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 1063411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 1064411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 1065411ba422e3635d534928ffd81abf54f4f291c739James Dong } 1066411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 1067411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 1068411ba422e3635d534928ffd81abf54f4f291c739James Dong } 106920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 107020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 107137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 10728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 107365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 1074fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int32_t nonImageTrackCount = 0; 107520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 1076fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang it != mTracks.end(); ++it) { 1077fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang status_t status = (*it)->stop(stopSource); 107837187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 107937187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 108037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 108120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1082fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // skip image tracks 1083fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if ((*it)->isHeic()) continue; 1084fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang nonImageTrackCount++; 1085fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 10868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 10878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 10888f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 108920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 109065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 109165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 109265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 109365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 109465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 1095fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (nonImageTrackCount > 1) { 1096a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us", 109765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 11017837c17063a4c50bc856ba59418516fdab731de7James Dong 110237187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 110337187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 1104411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 110537187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 110637187916a486504acaf83bea30147eb5fbf46ae5James Dong } 110737187916a486504acaf83bea30147eb5fbf46ae5James Dong 110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 11091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 1110c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 11111f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); 1112c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 11131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 1114c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 11151f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint64_t size = mOffset - mMdatOffset; 11161acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 1117c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 11181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 1119c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 112020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Construct moov box now 11227837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 11237b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = mStreamableFile; 11247b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 11257b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // There is no need to allocate in-memory cache 11267b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // for moov box if the file is not streamable. 11277b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 11287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 11297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong CHECK(mMoovBoxBuffer != NULL); 11307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 11317837c17063a4c50bc856ba59418516fdab731de7James Dong 1132fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mHasFileLevelMeta) { 1133fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeFileLevelMetaBox(); 1134fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mWriteMoovBoxToMemory) { 1135fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeCachedBoxToFile("meta"); 1136fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else { 1137fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGI("The file meta box is written at the end."); 1138fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1139fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 11407837c17063a4c50bc856ba59418516fdab731de7James Dong 1141fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mHasMoovBox) { 1142fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeMoovBox(maxDurationUs); 1143fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // mWriteMoovBoxToMemory could be set to false in 1144fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // MPEG4Writer::write() method 1145fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mWriteMoovBoxToMemory) { 1146fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeCachedBoxToFile("moov"); 1147fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else { 1148fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGI("The mp4 file will not be streamable."); 1149fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 11507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 1151fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mWriteMoovBoxToMemory = false; 11527837c17063a4c50bc856ba59418516fdab731de7James Dong 11537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Free in-memory cache for moov box 11547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mMoovBoxBuffer != NULL) { 11557837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 11567837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 11577837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 11587837c17063a4c50bc856ba59418516fdab731de7James Dong } 11597837c17063a4c50bc856ba59418516fdab731de7James Dong 11600c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1162411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 116337187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1166fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang/* 1167fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang * Writes currently cached box into file. 1168fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang * 1169fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang * Must be called while mWriteMoovBoxToMemory is true, and will not modify 1170fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang * mWriteMoovBoxToMemory. After the call, remaining cache size will be 1171fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang * reduced and buffer offset will be set to the beginning of the cache. 1172fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang */ 1173fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeCachedBoxToFile(const char *type) { 1174fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang CHECK(mWriteMoovBoxToMemory); 1175fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1176fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mWriteMoovBoxToMemory = false; 1177fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // Content of the moov box is saved in the cache, and the in-memory 1178fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // moov box needs to be written to the file in a single shot. 1179fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1180fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 1181fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1182fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // Cached box 1183fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang lseek64(mFd, mFreeBoxOffset, SEEK_SET); 1184fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mOffset = mFreeBoxOffset; 1185fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 1186fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1187fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // Free box 1188fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang lseek64(mFd, mOffset, SEEK_SET); 1189fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mFreeBoxOffset = mOffset; 1190fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 1191fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang write("free", 4); 1192fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1193fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // Rewind buffering to the beginning, and restore mWriteMoovBoxToMemory flag 1194fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mEstimatedMoovBoxSize -= mMoovBoxBufferOffset; 1195fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mMoovBoxBufferOffset = 0; 1196fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mWriteMoovBoxToMemory = true; 1197fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1198fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGV("dumped out %s box, estimated size remaining %lld", 1199fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang type, (long long)mEstimatedMoovBoxSize); 1200fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 1201fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1202efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() { 1203b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 1204efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 1205efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // while time function returns Unix epoch values which starts 1206efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // at 1970-01-01. Lets add the number of seconds between them 12072b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60); 12082b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen if (now < 0 || uint32_t(now) > UINT32_MAX - delta) { 12092b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen return 0; 12102b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen } 12112b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen uint32_t mpeg4Time = uint32_t(now) + delta; 1212efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson return mpeg4Time; 1213efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson} 1214efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson 1215efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 1216efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 1217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 1218b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 1219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 1220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 1221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 1222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 1223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 1224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 1225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 1226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 1227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 1230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 1237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 1238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 1241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 1242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 124307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 124407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 124507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 1246fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeMoovLevelMetaBox(); 1247230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang // Loop through all the tracks to get the global time offset if there is 1248230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang // any ctts table appears in a video track. 1249230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang int64_t minCttsOffsetTimeUs = kMaxCttsOffsetTimeUs; 1250b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 1251230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang it != mTracks.end(); ++it) { 1252fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!(*it)->isHeic()) { 1253fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang minCttsOffsetTimeUs = 1254fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang std::min(minCttsOffsetTimeUs, (*it)->getMinCttsOffsetTimeUs()); 1255fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1256230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang } 1257230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang ALOGI("Ajust the moov start time from %lld us -> %lld us", 1258230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang (long long)mStartTimestampUs, 1259230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang (long long)(mStartTimestampUs + minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs)); 1260230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang // Adjust the global start time. 1261230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang mStartTimestampUs += minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs; 1262230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang 1263230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang for (List<Track *>::iterator it = mTracks.begin(); 1264230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang it != mTracks.end(); ++it) { 1265fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!(*it)->isHeic()) { 1266fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang (*it)->writeTrackHeader(mUse32BitOffset); 1267fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1268b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1269b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 1270b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1271b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 12722cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 1273b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 1274b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1275b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 1276fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!param || !param->findInt32(kKeyFileType, &fileType)) { 1277fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang fileType = OUTPUT_FORMAT_MPEG_4; 1278fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1279fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (fileType != OUTPUT_FORMAT_MPEG_4 && fileType != OUTPUT_FORMAT_HEIF) { 1280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 12818284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 12828284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("isom"); 12838284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("3gp4"); 1284b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 1285fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // Only write "heic" as major brand if the client specified HEIF 1286fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // AND we indeed receive some image heic tracks. 1287fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (fileType == OUTPUT_FORMAT_HEIF && mHasFileLevelMeta) { 1288fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeFourcc("heic"); 1289fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else { 1290fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeFourcc("mp42"); 1291fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 12928284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 1293fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mHasFileLevelMeta) { 1294fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeFourcc("mif1"); 1295fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeFourcc("heic"); 1296fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1297fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mHasMoovBox) { 1298fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeFourcc("isom"); 1299fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeFourcc("mp42"); 1300fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 1304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1305b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 130607ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 130707ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 130807ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 130907ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 131007ec01904613a0bac32caaa8444b4690998faed7James Dong 131107ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 131207ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 131396626b7f9a4e5c9e1e04f7f710383631d1470364Marco Nelissen if (property_get_bool("rw.media.record.test", false)) { 131407ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 131507ec01904613a0bac32caaa8444b4690998faed7James Dong } 131607ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 131707ec01904613a0bac32caaa8444b4690998faed7James Dong} 131807ec01904613a0bac32caaa8444b4690998faed7James Dong 131970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 132007ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 132107ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 132207ec01904613a0bac32caaa8444b4690998faed7James Dong return; 132307ec01904613a0bac32caaa8444b4690998faed7James Dong } 132407ec01904613a0bac32caaa8444b4690998faed7James Dong 132570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 132670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 132770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 132870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 132970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 133070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 133170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 133270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 133370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 133413aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 133513aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 133613aec890216948b0c364f8f92792129d0335f506James Dong return OK; 133713aec890216948b0c364f8f92792129d0335f506James Dong} 133813aec890216948b0c364f8f92792129d0335f506James Dong 133913aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 134013aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 134113aec890216948b0c364f8f92792129d0335f506James Dong} 134213aec890216948b0c364f8f92792129d0335f506James Dong 134313aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 134413aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 134513aec890216948b0c364f8f92792129d0335f506James Dong} 134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1347fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangoff64_t MPEG4Writer::addSample_l( 1348fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang MediaBuffer *buffer, bool usePrefix, size_t *bytesWritten) { 1349c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1351fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (usePrefix) { 1352fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang addMultipleLengthPrefixedSamples_l(buffer); 1353fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else { 1354fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ::write(mFd, 1355fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang (const uint8_t *)buffer->data() + buffer->range_offset(), 1356fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang buffer->range_length()); 135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1358fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mOffset += buffer->range_length(); 1359fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1361fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang *bytesWritten = mOffset - old_offset; 136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 136603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 136703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 136803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 136903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 137003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 137103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 137203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 137303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 137403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 137503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 137603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 137703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 137803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1379fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) { 138080f78b773f92048944a850efb7b60629643370cdPraveen Chavan const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs 138180f78b773f92048944a850efb7b60629643370cdPraveen Chavan 138280f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset(); 138380f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *currentNalStart = dataStart; 138480f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *nextNalStart; 138580f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *data = dataStart; 138680f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t nextNalSize; 138780f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ? 138880f78b773f92048944a850efb7b60629643370cdPraveen Chavan kExtensionNALSearchRange : buffer->range_length(); 138980f78b773f92048944a850efb7b60629643370cdPraveen Chavan 139080f78b773f92048944a850efb7b60629643370cdPraveen Chavan while (getNextNALUnit(&data, &searchSize, &nextNalStart, 139180f78b773f92048944a850efb7b60629643370cdPraveen Chavan &nextNalSize, true) == OK) { 139210cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */; 139380f78b773f92048944a850efb7b60629643370cdPraveen Chavan MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize); 139480f78b773f92048944a850efb7b60629643370cdPraveen Chavan addLengthPrefixedSample_l(nalBuf); 139580f78b773f92048944a850efb7b60629643370cdPraveen Chavan nalBuf->release(); 139680f78b773f92048944a850efb7b60629643370cdPraveen Chavan 139780f78b773f92048944a850efb7b60629643370cdPraveen Chavan currentNalStart = nextNalStart; 139880f78b773f92048944a850efb7b60629643370cdPraveen Chavan } 139980f78b773f92048944a850efb7b60629643370cdPraveen Chavan 140080f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t currentNalOffset = currentNalStart - dataStart; 140180f78b773f92048944a850efb7b60629643370cdPraveen Chavan buffer->set_range(buffer->range_offset() + currentNalOffset, 140280f78b773f92048944a850efb7b60629643370cdPraveen Chavan buffer->range_length() - currentNalOffset); 140380f78b773f92048944a850efb7b60629643370cdPraveen Chavan addLengthPrefixedSample_l(buffer); 140480f78b773f92048944a850efb7b60629643370cdPraveen Chavan} 140580f78b773f92048944a850efb7b60629643370cdPraveen Chavan 1406fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 140730ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 140803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1409b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 1410b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 1411c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1412b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 1413c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1414b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 1415c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1416b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1417c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1418c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 1419c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1420c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1421c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 1422b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1423b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 1424b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 1425b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_LT(length, 65536u); 142630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1427b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 1428c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1429b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1430c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1431c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1432b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 1433b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 143430ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 143530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 14367837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 1437674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 14387837c17063a4c50bc856ba59418516fdab731de7James Dong 14397837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 14407837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 14417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 1442c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 14431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 14447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // The reserved moov box at the beginning of the file 14457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // is not big enough. Moov box should be written to 14467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the end of the file from now on, but not to the 14477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // in-memory cache. 14487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 14497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // We write partial moov box that is in the memory to 14507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the file first. 1451c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 14527837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 14537837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 14547837c17063a4c50bc856ba59418516fdab731de7James Dong } 1455674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 1456674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 14577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ::write(mFd, ptr, bytes); 14587837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 14597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 14607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // All subsequent moov box content will be written 14617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // to the end of the file. 14627837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 14637837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 14647837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 14657837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 14667837c17063a4c50bc856ba59418516fdab731de7James Dong } 14677837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1468674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 14697837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 14707837c17063a4c50bc856ba59418516fdab731de7James Dong } 14717837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 14727837c17063a4c50bc856ba59418516fdab731de7James Dong} 14737837c17063a4c50bc856ba59418516fdab731de7James Dong 1474e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) { 1475e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mBoxes.push_back(mWriteMoovBoxToMemory? 1476e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mMoovBoxBufferOffset: mOffset); 1477e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 1478e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 1479e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(id); 1480e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1481e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 148220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 1483b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_EQ(strlen(fourcc), 4u); 148420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14857837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 14867837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 148720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 148820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 149020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 14930c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 149420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1495c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 149620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 149720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14987837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 1499fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int32_t x = htonl(mMoovBoxBufferOffset - offset); 1500fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang memcpy(mMoovBoxBuffer + offset, &x, 4); 15017837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1502c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 15037837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 15047837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1505c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 15067837c17063a4c50bc856ba59418516fdab731de7James Dong } 150720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 150920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1510674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 151120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 151220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 151320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 151420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1515674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 151620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 151720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1520674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1525674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1530674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 1534b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_EQ(strlen(s), 4u); 1535674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 153807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 153907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 154007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 154107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 154207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 154307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 154407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 154507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 154607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 154707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 154807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 154907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 155007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 155107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 155207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 155307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 155407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 155507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 155607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 155707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 155807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 155907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 156007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 156107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 156207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 156307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 156407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 156507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 156607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 156707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 156807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 156907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 157007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 157107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 157207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 157307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 157407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 157507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 157607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 157707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 157807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 157907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 158007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 158107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 158207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 158307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 158407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 158507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 158607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 158707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 158807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 158907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 159007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 159107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 159207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 159307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 159407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 159507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 159607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 159707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 159807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 159907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 160007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 160107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 160207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 160307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 160407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 160507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 16067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 30; 160707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 160807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 160907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 1610e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) { 1611e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (captureFps <= 0.0f) { 1612e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return BAD_VALUE; 1613e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 1614e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 16157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps); 16167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32; 16177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 1618e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return OK; 1619e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1620e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 16214dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) { 16224dbff11975e737482537e1636051690188f3fbc4Praveen Chavan if (layerCount > 9) { 16234dbff11975e737482537e1636051690188f3fbc4Praveen Chavan return BAD_VALUE; 16244dbff11975e737482537e1636051690188f3fbc4Praveen Chavan } 16254dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 16264dbff11975e737482537e1636051690188f3fbc4Praveen Chavan if (layerCount > 0) { 16274dbff11975e737482537e1636051690188f3fbc4Praveen Chavan mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount); 16284dbff11975e737482537e1636051690188f3fbc4Praveen Chavan mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32; 16294dbff11975e737482537e1636051690188f3fbc4Praveen Chavan } 16304dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 16314dbff11975e737482537e1636051690188f3fbc4Praveen Chavan return OK; 16324dbff11975e737482537e1636051690188f3fbc4Praveen Chavan} 16334dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 1634fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::notifyApproachingLimit() { 1635fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang Mutex::Autolock autolock(mLock); 1636fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // Only notify once. 1637fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mSendNotify) { 1638fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return; 1639fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1640fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGW("Recorded file size is approaching limit %" PRId64 "bytes", 1641fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMaxFileSizeLimitBytes); 1642fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING, 0); 1643fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSendNotify = true; 1644fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1645fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 164620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1647674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 164820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 164920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 165078a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 165178a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 165278a1a286f736888ae7af8860b2c424af0d978848James Dong} 165378a1a286f736888ae7af8860b2c424af0d978848James Dong 1654d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1655d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1656d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1657d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1658d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1659956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1660d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1661d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1662d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1663d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 16641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 166577e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 166677e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 166777e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 166877e8ae9967a078770416619e99ddb5b010def312James Dong } 1669fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1670acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1671acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1672acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1673acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1674d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1675d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1676fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangbool MPEG4Writer::approachingFileSizeLimit() { 1677fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // No limit 1678fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mMaxFileSizeLimitBytes == 0) { 1679fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return false; 1680fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1681fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1682fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1683fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang for (List<Track *>::iterator it = mTracks.begin(); 1684fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang it != mTracks.end(); ++it) { 1685fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1686fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1687fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1688fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (!mStreamableFile) { 1689fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // Add 1024 bytes as error tolerance 1690fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return nTotalBytesEstimate + 1024 >= (90 * mMaxFileSizeLimitBytes) / 100; 1691fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1692fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1693fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return (nTotalBytesEstimate >= (90 * mMaxFileSizeLimitBytes) / 100); 1694fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1695fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1696d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1697d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1698d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1699d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1700d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1701d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1702d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1703d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1704fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!(*it)->isHeic() && (*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1705d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1706d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1707d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1708d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1709d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1710d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 171125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 171225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 171325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 171425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 171525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 171625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 171725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 171825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 171925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 172025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 172125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 172225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 172325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1724f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1725a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("setStartTimestampUs: %" PRId64, timeUs); 172643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 17273c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1728065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1729f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1730a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs); 17313c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 17323c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 17333c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1734f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 17353c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 17363c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 17373c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 17383c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 173958ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 174058ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 174158ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 174258ae9c530247668f8af36e30d228c716c226b3d4James Dong} 174358ae9c530247668f8af36e30d228c716c226b3d4James Dong 174420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 174520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 174620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1747ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kang MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 174820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 174925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 175020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 175120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1752a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1753a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1754eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1755fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mGotStartKeyFrame(false), 17569db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed(false), 1757bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1758c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1759956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1760be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1761c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1762c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1763c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)), 1764c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)), 1765c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1766c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)), 1767c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)), 1768230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang mMinCttsOffsetTimeUs(0), 1769230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang mMinCttsOffsetTicks(0), 1770230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang mMaxCttsOffsetTicks(0), 177120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 177225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1773548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 177413f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 1775a9292fe1c19e8a9b43398ba3d69284c215d7589fRobert Shih mStartTimestampUs(-1), 1776fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mRotation(0), 1777fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mIsPrimary(0), 1778fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mWidth(0), 1779fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mHeight(0), 1780fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mGridWidth(0), 1781fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mGridHeight(0), 1782fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mGridRows(0), 1783fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mGridCols(0), 1784fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mNumTiles(1), 1785fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mTileIndex(0) { 178619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 17878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 17881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 17891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 17901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 17919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC); 17921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 179325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mIsVideo = !strncasecmp(mime, "video/", 6); 1794fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mIsHeic = !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC); 17951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 17961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 17971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1798b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar // store temporal layer count 179925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo) { 1800b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar int32_t count; 1801b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) { 1802b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar mOwner->setTemporalLayerCount(count); 1803b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar } 1804b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar } 1805b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar 1806fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!mIsHeic) { 1807fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang setTimeScale(); 1808fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else { 1809fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang CHECK(mMeta->findInt32(kKeyWidth, &mWidth) && (mWidth > 0)); 1810fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang CHECK(mMeta->findInt32(kKeyHeight, &mHeight) && (mHeight > 0)); 1811fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1812fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int32_t gridWidth, gridHeight, gridRows, gridCols; 1813fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mMeta->findInt32(kKeyGridWidth, &gridWidth) && (gridWidth > 0) && 1814fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mMeta->findInt32(kKeyGridHeight, &gridHeight) && (gridHeight > 0) && 1815fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mMeta->findInt32(kKeyGridRows, &gridRows) && (gridRows > 0) && 1816fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mMeta->findInt32(kKeyGridCols, &gridCols) && (gridCols > 0)) { 1817fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mGridWidth = gridWidth; 1818fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mGridHeight = gridHeight; 1819fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mGridRows = gridRows; 1820fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mGridCols = gridCols; 1821fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mNumTiles = gridRows * gridCols; 1822fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1823fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!mMeta->findInt32(kKeyTrackIsDefault, &mIsPrimary)) { 1824fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mIsPrimary = false; 1825fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1826fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1827c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1828c059860c73678a202bfa33062723e8f82fb779d9James Dong 1829fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang// Clear all the internal states except the CSD data. 1830fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::Track::resetInternal() { 1831fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mDone = false; 1832fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mPaused = false; 1833fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mResumed = false; 1834fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStarted = false; 1835fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mGotStartKeyFrame = false; 1836fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mIsMalformed = false; 1837fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mTrackDurationUs = 0; 1838fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mEstimatedTrackSizeBytes = 0; 1839fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSamplesHaveSameSize = 0; 1840fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mStszTableEntries != NULL) { 1841fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mStszTableEntries; 1842fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000); 1843fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1844fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1845fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mStcoTableEntries != NULL) { 1846fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mStcoTableEntries; 1847fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000); 1848fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1849fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mCo64TableEntries != NULL) { 1850fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mCo64TableEntries; 1851fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000); 1852fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1853fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1854fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mStscTableEntries != NULL) { 1855fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mStscTableEntries; 1856fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000); 1857fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1858fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mStssTableEntries != NULL) { 1859fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mStssTableEntries; 1860fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000); 1861fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1862fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mSttsTableEntries != NULL) { 1863fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mSttsTableEntries; 1864fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000); 1865fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1866fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mCttsTableEntries != NULL) { 1867fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mCttsTableEntries; 1868fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000); 1869fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1870fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mReachedEOS = false; 1871fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1872fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 18731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 1874fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 18751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1876fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!isHeic() && !mOwner->isFileStreamable()) { 1877fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1878fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ? mStcoTableEntries->count() 1879fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang : mCo64TableEntries->count()); 1880fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1881fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 18821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 188378a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 188478a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1885c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1886c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1887c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1888c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 188978a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 189078a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 189178a1a286f736888ae7af8860b2c424af0d978848James Dong } 18921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 18931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 18941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 18951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 1896fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mStscTableEntries->add(htonl(chunkId)); 1897fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mStscTableEntries->add(htonl(sampleId)); 1898fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mStscTableEntries->add(htonl(1)); 18991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 19001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 19011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1902c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 19031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 19041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 19051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 190679761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 19071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 19085a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 1909377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGW("0-duration samples found: %zu", sampleCount); 19105a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1911c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1912c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 19131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 19141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1915965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1916965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1917965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 191825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (!mIsVideo) { 1919965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1920965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1921c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1922c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1923965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1924965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1925fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::setNextFd(int fd) { 1926fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGV("addNextFd"); 1927fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang Mutex::Autolock l(mLock); 1928fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mLooper == NULL) { 1929fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mReflector = new AHandlerReflector<MPEG4Writer>(this); 1930fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLooper = new ALooper; 1931fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLooper->registerHandler(mReflector); 1932fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLooper->start(); 1933fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1934fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1935fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mNextFd != -1) { 1936fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // No need to set a new FD yet. 1937fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return INVALID_OPERATION; 1938fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1939fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mNextFd = fd; 1940fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return OK; 1941fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1942fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1943c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1944fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang CHECK(!mIsHeic); 1945c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1946c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1947c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1948c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1949c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1950c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 19511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 19521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1953fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::Track::addItemOffsetAndSize(off64_t offset, size_t size) { 1954fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang CHECK(mIsHeic); 1955fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1956fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (offset > UINT32_MAX || size > UINT32_MAX) { 1957fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGE("offset or size is out of range: %lld, %lld", 1958fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang (long long) offset, (long long) size); 1959fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mIsMalformed = true; 1960fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1961fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mIsMalformed) { 1962fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang return; 1963fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1964fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mTileIndex >= mNumTiles) { 1965fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGW("Ignoring excess tiles!"); 1966fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang return; 1967fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1968fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1969fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mProperties.empty()) { 1970fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mProperties.push_back(mOwner->addProperty_l({ 1971fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .type = FOURCC('h', 'v', 'c', 'C'), 1972fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .hvcc = ABuffer::CreateAsCopy(mCodecSpecificData, mCodecSpecificDataSize) 1973fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang })); 1974fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1975fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mProperties.push_back(mOwner->addProperty_l({ 1976fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .type = FOURCC('i', 's', 'p', 'e'), 1977fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .width = (mNumTiles > 1) ? mGridWidth : mWidth, 1978fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .height = (mNumTiles > 1) ? mGridHeight : mHeight, 1979fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang })); 1980fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 1981fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1982fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang uint16_t itemId = mOwner->addItem_l({ 1983fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .itemType = "hvc1", 1984fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .isPrimary = (mNumTiles > 1) ? false : (mIsPrimary != 0), 1985fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .isHidden = (mNumTiles > 1), 1986fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .offset = (uint32_t)offset, 1987fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .size = (uint32_t)size, 1988fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .properties = mProperties, 1989fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang }); 1990fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1991fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mTileIndex++; 1992fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mNumTiles > 1) { 1993fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mDimgRefs.push_back(itemId); 1994fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 1995fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mTileIndex == mNumTiles) { 1996fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mProperties.clear(); 1997fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mProperties.push_back(mOwner->addProperty_l({ 1998fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .type = FOURCC('i', 's', 'p', 'e'), 1999fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .width = mWidth, 2000fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .height = mHeight, 2001fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang })); 2002fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mOwner->addItem_l({ 2003fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .itemType = "grid", 2004fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .isPrimary = (mIsPrimary != 0), 2005fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .isHidden = false, 2006fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .rows = (uint32_t)mGridRows, 2007fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .cols = (uint32_t)mGridCols, 2008fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .width = (uint32_t)mWidth, 2009fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .height = (uint32_t)mHeight, 2010fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .properties = mProperties, 2011fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang .dimgRefs = mDimgRefs, 2012fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang }); 2013fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 2014fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 2015fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 2016fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 2017c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 20183856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 2019c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 2020c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 2021c059860c73678a202bfa33062723e8f82fb779d9James Dong 2022c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 2023c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 2024c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 2025c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 2026c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 2027c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 2028c059860c73678a202bfa33062723e8f82fb779d9James Dong } 2029c059860c73678a202bfa33062723e8f82fb779d9James Dong 2030c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 2031c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 2032c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 2033c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 2034c059860c73678a202bfa33062723e8f82fb779d9James Dong } 2035c059860c73678a202bfa33062723e8f82fb779d9James Dong 203643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 203719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 203819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 2039fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::onMessageReceived(const sp<AMessage> &msg) { 2040fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang switch (msg->what()) { 2041fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang case kWhatSwitch: 2042fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang { 2043fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang finishCurrentSession(); 2044fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLock.lock(); 2045fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang int fd = mNextFd; 2046fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mNextFd = -1; 2047fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLock.unlock(); 20485ba45163872df39427cf18b3d640e1cd26c228bbHangyu Kuang initInternal(fd, false /*isFirstSession*/); 2049fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang start(mStartMeta.get()); 2050fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSwitchPending = false; 2051fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED, 0); 2052fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang break; 2053fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2054fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang default: 2055fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang TRESPASS(); 2056fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2057fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 2058fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 205919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 206019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 2061fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 206219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 206319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 20649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim uint32_t type; 20659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const void *data = NULL; 20669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t size = 0; 206719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 20689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mMeta->findData(kKeyAVCC, &type, &data, &size); 2069fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC) || 2070fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) { 20719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mMeta->findData(kKeyHVCC, &type, &data, &size); 207219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 207319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 207419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 207519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 2076212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa if (esds.getCodecSpecificInfo(&data, &size) == OK && 2077212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa data != NULL && 2078212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa copyCodecSpecificData((uint8_t*)data, size) == OK) { 2079212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa mGotAllCodecSpecificData = true; 208019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 2081212335cbc6e8795c3cfb332e7b119e03cf33f603Pawin Vongmasa return; 208219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 208319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 20849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) { 20859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mGotAllCodecSpecificData = true; 20869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 208720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 208820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 208920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 209020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 209120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2092c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 2093c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 2094c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 2095c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 2096c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 2097c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 2098c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 2099c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2100c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 2101c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 2102c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 2103c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 2104c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 2105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 2106c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 2107c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 210820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 210920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 211020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 211120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 211220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 211320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 211493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 21153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 211693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 211793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 211893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 211993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 212093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 212193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 2122a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs); 212393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 212493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 212593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 212693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 212793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 212893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 21291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 21301c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 21313856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 21321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 21331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 21341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 21351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 21361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 21371c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 21383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 21391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 21401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 21411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 21421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 21431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 21441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 21451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 21461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 21471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 21481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 21491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 21501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 21511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 215243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 21531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 21541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 2155fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 2156a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("writeChunkToFile: %" PRId64 " from %s track", 215725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang chunk->mTimeStampUs, chunk->mTrack->getTrackType()); 2158fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 2159fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 2160fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang bool usePrefix = chunk->mTrack->usePrefix(); 2161fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 2162fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 2163fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 2164fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang size_t bytesWritten; 2165fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang off64_t offset = addSample_l(*it, usePrefix, &bytesWritten); 2166fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 2167fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (chunk->mTrack->isHeic()) { 2168fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang chunk->mTrack->addItemOffsetAndSize(offset, bytesWritten); 2169fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else if (isFirstSample) { 2170fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 2171fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 21721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 21731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 21741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 21751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 2176fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 21771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 2178fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 21791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 21801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 2181fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 21823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 21831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 218470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 218570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 2186e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 218770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 21881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 218970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 219070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 219170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 21921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 2193377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGD("%zu chunks are written in the last batch", outstandingChunks); 21941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 21951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 2196fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 21973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 21981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 21991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 22001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 22011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 22021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 22031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 22041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 22051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 22061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 22071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 22081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 22091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 22101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 22111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 22121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 22133856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 2214fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 22151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 22161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 22171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 22181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 22191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 2220fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 22211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 22221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 22231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 2224fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 2225fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 2226fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 222770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 222870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 222970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 223070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 223170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 223270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 223370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 2234fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 22351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 22361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 2237fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 2238fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 22391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 22401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 22411c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 22423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 22431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 2244a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 2245fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 2246fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 22471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 2248fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 2249fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 2250fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 2251fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 22521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 22531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 22541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 2255de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // In real time recording mode, write without holding the lock in order 2256de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // to reduce the blocking time for media track threads. 2257de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // Otherwise, hold the lock until the existing chunks get written to the 2258de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // file. 2259fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 2260de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 2261de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.unlock(); 2262de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2263fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 2264de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 2265de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.lock(); 2266de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2267fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 22681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 2269fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 2270fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 22711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 22721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 22731c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 22743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 22751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 22761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 22771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 2278e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 22791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 22801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 22811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 22821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 228370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 228470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 22851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 22861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 22871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 22881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 22891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 22901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 22911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 22921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 2293411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 22941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 22951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 22961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 22971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 229893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 2299a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 2300a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 2301a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 2302a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 2303a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 230425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 230593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 230619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 230719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 230819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 230970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 231019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 231113f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 231225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 231313f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 231413f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 231513f6284305e4b27395a23db7882d670bdb1bcae1James Dong 231693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 231793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2318f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 2319de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 2320a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 2321a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 2322a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 2323a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 2324a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 2325a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 232686b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 232786b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 2328a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 232986b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 233086b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 233186b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 233286b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 233386b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 2334a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs); 2335a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2336a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2337f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 2338a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2339f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 234025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 234125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 234225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 234325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 234420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 234520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 234620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 234720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 234820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 234920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 2350eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 2351c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 235225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 2353956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 23541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 235543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 2356826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar mLastDecodingTimeUs = -1; 235720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 235825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 235920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 236025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 236125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 236220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 236320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 236437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 2365a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 236637187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 2367a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 2368a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2369fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::Track::stop(bool stopSource) { 2370fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("%s track stopping. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop"); 2371eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 237229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 2373eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 2374eaae38445a340c4857c1c5569475879a728e63b7James Dong } 2375eaae38445a340c4857c1c5569475879a728e63b7James Dong 237620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 237737187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 237820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 2379f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang 2380fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (stopSource) { 2381fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("%s track source stopping", getTrackType()); 2382fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSource->stop(); 2383fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("%s track source stopped", getTrackType()); 2384fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 238572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 2386f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang // Set mDone to be true after sucessfully stop mSource as mSource may be still outputting 2387f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang // buffers to the writer. 2388f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang mDone = true; 2389f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang 239020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 239120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 2392377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 239337187916a486504acaf83bea30147eb5fbf46ae5James Dong 2394fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("%s track stopped. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop"); 239537187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 239620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 239720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 239825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 239925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 240025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 240125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 240220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 240320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 240420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 240520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 240637187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 2407377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT return (void *)(uintptr_t)err; 240820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 240920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 24113856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 24123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 24133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 24143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 24153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 24163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 24173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 24183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 24193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 24203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 24213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 24223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 24233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 242447d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar const uint8_t *nextStartCode = findNextNalStartCode(data, length); 24253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 24263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 242729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 24283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 24293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 24303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 24313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 24323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 24333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 243429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 24353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 24363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 24373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 24383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 24393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 24403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 24413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 24423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 24433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 24443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 244507b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar // COULD DO: set profile/level to the lowest required to support all SPSs 244629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 24473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 24483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 24493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 24503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 24513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 24523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 24533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 24543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 24553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 24563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 24573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 24583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 24593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 24603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 24613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 24623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 24639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyCodecSpecificData(data, size, 4 + 7); 24649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 24659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData( 24679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size) { 24689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGV("copyHEVCCodecSpecificData"); 24699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2) 24719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyCodecSpecificData(data, size, 23); 24729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 24739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData( 24759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, size_t minLength) { 24769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (size < minLength) { 2477377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 24783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 24793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 24803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 24813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 24829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 24839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 24849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 24859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = size; 24873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 24883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 24893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 24903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 24913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 24923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 24933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 24943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 24953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 24963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 24973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 24983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 24993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 25003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 25013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 25023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 25033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 25043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 25053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 25063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 25073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 25083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 25093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 251029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 25113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 25123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 25143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 25153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 25173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 25183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 251929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 25203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 25213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 25233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 25243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 25263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 252729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 25283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 25293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 25313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 25323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 25333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 25353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 25363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 25373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 25383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 25393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 25413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 25423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 25433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 25443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 254529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 25463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 25473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 25493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 2550377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 25513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 25523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 25553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 25563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 25573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 25583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 255929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 25603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 25613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 2563377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 25643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 25653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25671374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 25681374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 25691374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 25701374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 25713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 25723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 25733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 25743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 25753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 257629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 25773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 25783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 25801374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 25813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 25823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 2583548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 258403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 258503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 2586548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 258703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 258829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 258903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 259003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 259103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 25923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 2593377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 259403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 259503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 259603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 25973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 25983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 25993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 260003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 260103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 26023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 260303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 260403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 260503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 26063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 26073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 260803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 26099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 26109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = 0; 26119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 26129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 26139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 261403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 26153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 26163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 26173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 26183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 261903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 26203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2621b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2622b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 2623b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2624b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 2625b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 262603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 26273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 26283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 26293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 26303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 26313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 26323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 26333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 26343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 26353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 26363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 26373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 26383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 26393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 26403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 26413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 26423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 26433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 26443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 26453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 26463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 26473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 26483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 26493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 26503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 26513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 26523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 26533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 26543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 26553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 26563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 26573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 265803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 265903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 266003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 266103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 26629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 26639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData( 26649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, HevcParameterSets ¶mSets) { 26659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 26669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGV("parseHEVCCodecSpecificData"); 26679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *tmp = data; 26689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *nextStartCode = data; 26699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t bytesLeft = size; 26709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 267147d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4); 26729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4); 26739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (err != OK) { 26749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 26759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 26769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 26779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Move on to find the next parameter set 26789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bytesLeft -= nextStartCode - tmp; 26799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim tmp = nextStartCode; 26809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 26819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 26829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t csdSize = 23; 26839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const size_t numNalUnits = paramSets.getNumNalUnits(); 26849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) { 26859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim int type = kMandatoryHevcNalUnitTypes[i]; 26869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 26879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (numParamSets == 0) { 26889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Cound not find NAL unit of type %d", type); 26899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 26909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 26919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 26929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) { 26939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim int type = kHevcNalUnitTypes[i]; 26949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 26959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (numParamSets > 0xffff) { 26969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Too many seq parameter sets (%zu) found", numParamSets); 26979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 26989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 26999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim csdSize += 3; 27009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t j = 0; j < numNalUnits; ++j) { 27019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (paramSets.getType(j) != type) { 27029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim continue; 27039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 27049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim csdSize += 2 + paramSets.getSize(j); 27059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 27069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 27079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = csdSize; 27089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return OK; 27099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 27109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 27119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData( 27129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size) { 27139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 27149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData != NULL) { 27159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Already have codec specific data"); 27169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 27179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 27189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 27199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (size < 4) { 27209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Codec specific data length too short: %zu", size); 27219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 27229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 27239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 27249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Data is in the form of HEVCCodecSpecificData 27259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (memcmp("\x00\x00\x00\x01", data, 4)) { 27269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyHEVCCodecSpecificData(data, size); 27279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 27289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 27299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim HevcParameterSets paramSets; 27309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) { 27313d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim ALOGE("failed parsing codec specific data"); 27329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 27339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 27349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 27359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificData = malloc(mCodecSpecificDataSize); 27369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 27379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = 0; 27389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 27399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 27409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 27419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData, 27423d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2); 27439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (err != OK) { 27443d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim ALOGE("failed constructing HVCC atom"); 27459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return err; 27469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 27479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 27489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return OK; 27499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 27509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 2751872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 2752872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 2753872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 2754872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 2755872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 2756872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2757872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 2758872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 2759872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2760872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 2761872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2762872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2763872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2764872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 2765872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2766872a481558350634a3fd5cb67939de288af00ecbJames Dong} 2767872a481558350634a3fd5cb67939de288af00ecbJames Dong 276862a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuangvoid MPEG4Writer::Track::dumpTimeStamps() { 2769dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang ALOGE("Dumping %s track's last 10 frames timestamp and frame type ", getTrackType()); 277062a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang std::string timeStampString; 2771dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang for (std::list<TimestampDebugHelperEntry>::iterator entry = mTimestampDebugHelper.begin(); 2772dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang entry != mTimestampDebugHelper.end(); ++entry) { 2773dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang timeStampString += "(" + std::to_string(entry->pts)+ 2774dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang "us, " + std::to_string(entry->dts) + "us " + entry->frameType + ") "; 277562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang } 277662a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang ALOGE("%s", timeStampString.c_str()); 277762a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang} 277862a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang 277937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 278030ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 278113aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 278243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 278313aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 278413aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 27857c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar int32_t nActualFrames = 0; // frames containing non-CSD data (non-0 length) 278613aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 2787965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 2788965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 2789965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 2790965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 2791965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 2792000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 2793a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 2794965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 2795000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 2796000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2797000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 279843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2799c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 2800e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2801a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 2802a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 280325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (mIsVideo) { 2804a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 280525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else { 280625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0); 2807a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 2808de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2809de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2810de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2811de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2812985f838934510983d8a887461e98dca60a6e858fJames Dong 2813d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 281420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 281593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 281620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 281725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *trackName = getTrackType(); 281893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 281920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 282020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 282120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 282213aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 282320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 282420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 282520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2826a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 2827a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 2828a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2829a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2830a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2831a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2832a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2833a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2834a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 283530ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 283630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 283703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 283803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 283903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 28407c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // if config format (at track addition) already had CSD, keep that 28417c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // UNLESS we have not received any frames yet. 28427c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // TODO: for now the entire CSD has to come in one frame for encoders, even though 28437c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // they need to be spread out for decoders. 28447c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar if (mGotAllCodecSpecificData && nActualFrames > 0) { 28457c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar ALOGI("ignoring additional CSD for video track after first frame"); 28467c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else { 28477c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar mMeta = mSource->getFormat(); // get output format after format change 28486e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang status_t err; 28497c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar if (mIsAvc) { 28506e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang err = makeAVCCodecSpecificData( 28517c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar (const uint8_t *)buffer->data() 28527c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar + buffer->range_offset(), 28537c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 2854fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else if (mIsHevc || mIsHeic) { 28556e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang err = makeHEVCCodecSpecificData( 28567c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar (const uint8_t *)buffer->data() 28577c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar + buffer->range_offset(), 28587c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 28597c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else if (mIsMPEG4) { 28607c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(), 28617c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 28627c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } 286330ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 286430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 286530ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 286630ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 28676e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang if (OK != err) { 28686e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang mSource->stop(); 28696e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 28706e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang mTrackId | MEDIA_RECORDER_TRACK_ERROR_GENERAL, err); 28716e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang break; 28726e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang } 287330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2874548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 287530ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2876a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2877a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2878e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang // Per-frame metadata sample's size must be smaller than max allowed. 2879fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!mIsVideo && !mIsAudio && !mIsHeic && 2880fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang buffer->range_length() >= kMaxMetadataSize) { 2881e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang ALOGW("Buffer size is %zu. Maximum metadata buffer size is %lld for %s track", 2882e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang buffer->range_length(), (long long)kMaxMetadataSize, trackName); 2883e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang buffer->release(); 2884e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang mSource->stop(); 2885e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang mIsMalformed = true; 2886e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang break; 2887e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang } 2888e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang 28897c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar ++nActualFrames; 28907c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar 2891d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2892d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2893d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2894d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2895d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2896d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2897d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2898d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2899d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2900d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2901fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (usePrefix()) StripStartcode(copy); 2902e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2903b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 2904fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (usePrefix()) { 2905b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2906b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2907b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2908b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2909b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2910b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2911050b28a593350047845a45a14cc5026221ac1620James Dong 2912d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 29131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 29141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 29151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2916d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2917fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mOwner->switchFd() != OK) { 2918fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGW("Recorded file size exceeds limit %" PRId64 "bytes", 2919fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mOwner->mMaxFileSizeLimitBytes); 2920fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSource->stop(); 2921fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mOwner->notify( 2922fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2923fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } else { 2924fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGV("%s Current recorded file size exceeds limit %" PRId64 "bytes. Switching output", 2925fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang getTrackType(), mOwner->mMaxFileSizeLimitBytes); 2926fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2927d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang copy->release(); 2928d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2929d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2930fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 2931d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2932316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds", 2933316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang mOwner->mMaxFileDurationLimitUs); 2934d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2935d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang copy->release(); 2936d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 2937d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2938d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2939d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2940fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mOwner->approachingFileSizeLimit()) { 2941fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mOwner->notifyApproachingLimit(); 2942fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2943050b28a593350047845a45a14cc5026221ac1620James Dong 2944d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2945d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2946d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2947d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2948fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // For video, skip the first several non-key frames until getting the first key frame. 2949fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mIsVideo && !mGotStartKeyFrame && !isSync) { 2950fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("Video skip non-key frame"); 2951fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang copy->release(); 2952fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang continue; 2953fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2954fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mIsVideo && isSync) { 2955fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mGotStartKeyFrame = true; 2956fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2957d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2958c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 295970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2960f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2961f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 29628428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 29633c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 296448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2965a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 29668428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 296711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) { 296811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2969d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 29709db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 29719db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 297211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 297311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 29748428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 297511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) { 297611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2977d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 29789db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 29799db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 298011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 298111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 29828428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2983a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2984a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2985dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang TimestampDebugHelperEntry timestampDebugEntry; 2986a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 2987dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang timestampDebugEntry.pts = timestampUs; 298811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 298911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2990d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 29919db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 29929db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 299311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 299411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 299525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo) { 2996965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2997965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2998965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2999000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 3000965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 3001965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 3002965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 3003965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 3004826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar 3005826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar // ensure non-negative, monotonic decoding time 3006826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar if (mLastDecodingTimeUs < 0) { 3007826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar decodingTimeUs = std::max((int64_t)0, decodingTimeUs); 3008826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar } else { 300938f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang // increase decoding time by at least the larger vaule of 1 tick and 301038f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang // 0.1 milliseconds. This needs to take into account the possible 301138f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang // delta adjustment in DurationTicks in below. 301238f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang decodingTimeUs = std::max(mLastDecodingTimeUs + 301338f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang std::max(100, divUp(1000000, mTimeScale)), decodingTimeUs); 3014826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar } 3015826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar 3016826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar mLastDecodingTimeUs = decodingTimeUs; 3017dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang timestampDebugEntry.dts = decodingTimeUs; 3018dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang timestampDebugEntry.frameType = isSync ? "Key frame" : "Non-Key frame"; 3019dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang // Insert the timestamp into the mTimestampDebugHelper 3020dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang if (mTimestampDebugHelper.size() >= kTimestampDebugCount) { 3021dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang mTimestampDebugHelper.pop_front(); 3022dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang } 3023dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang mTimestampDebugHelper.push_back(timestampDebugEntry); 3024dfa827d957d4763dd4685ed7299699b6aaae8072Hangyu Kuang 3025000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 3026000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 302711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) { 302811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 3029d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 30309db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 30319db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 303211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 303311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 3034965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 3035a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64, 3036000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 3037000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3038000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 3039000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 3040000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 304111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) { 304211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 3043d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 30449db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 30459db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 304611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 304711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 3048c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 304943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 305043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 305143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 305243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 305343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 305443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 305543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 305643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 305743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 305843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 305943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 306043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 306143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 306243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 306343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 3064000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3065000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 3066c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 3067230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang mMinCttsOffsetTicks = currCttsOffsetTimeTicks; 3068230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang mMaxCttsOffsetTicks = currCttsOffsetTimeTicks; 3069000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 3070230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang if (currCttsOffsetTimeTicks > mMaxCttsOffsetTicks) { 3071230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang mMaxCttsOffsetTicks = currCttsOffsetTimeTicks; 3072230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTicks) { 3073230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang mMinCttsOffsetTicks = currCttsOffsetTimeTicks; 3074230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang mMinCttsOffsetTimeUs = cttsOffsetTimeUs; 3075000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 3076000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 3077965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3078872a481558350634a3fd5cb67939de288af00ecbJames Dong 3079de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 3080872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 3081872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 3082e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 3083e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 3084872a481558350634a3fd5cb67939de288af00ecbJames Dong 308511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 308611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 3087d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 30889db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 30899db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 309011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 309111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 3092a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64, 309311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, previousPausedDurationUs); 3094c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 3095c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 30963b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 30973b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 30985a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 30995a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 31005a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 31015a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 31025a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 31035a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 31045a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 31055a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 3106c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 3107f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track", 3108f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang (long long)timestampUs, (long long)lastTimestampUs, trackName); 310911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 31100332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang mSource->stop(); 31119db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 31129db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 31138c460498c028888c533ab442be12b6d4b669b965James Dong } 31148c460498c028888c533ab442be12b6d4b669b965James Dong 311585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // if the duration is different for this sample, see if it is close enough to the previous 311685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // duration that we can fudge it and use the same value, to avoid filling the stts table 311785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // with lots of near-identical entries. 311885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // "close enough" here means that the current duration needs to be adjusted by less 311985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // than 0.1 milliseconds 312085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { 312185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL 312285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen + (mTimeScale / 2)) / mTimeScale; 312385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (deltaUs > -100 && deltaUs < 100) { 312485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // use previous ticks, and adjust timestamp as if it was actually that number 312585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // of ticks 312685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen currDurationTicks = lastDurationTicks; 312785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen timestampUs += deltaUs; 312885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 312985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 3130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 3131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 3132c059860c73678a202bfa33062723e8f82fb779d9James Dong 3133a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 3134a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 3135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 313679761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 3137be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 3138be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 3139be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 3140be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 3141965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3142be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 3143be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 3144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 3145be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 3146be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 31478644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 3148be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 3149a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64, 315011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, lastTimestampUs); 31518644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 3152c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 31538644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 315420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3155d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 3156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 3157d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 3158d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 315993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 316093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 316193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 316293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 3163faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 316493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 316543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 3166fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang size_t bytesWritten; 3167fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang off64_t offset = mOwner->addSample_l(copy, usePrefix(), &bytesWritten); 3168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 3169fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mIsHeic) { 3170fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang addItemOffsetAndSize(offset, bytesWritten); 3171fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else { 3172fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang uint32_t count = (mOwner->use32BitFileOffset() 3173fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ? mStcoTableEntries->count() 3174fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang : mCo64TableEntries->count()); 3175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 3176fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (count == 0) { 3177fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang addChunkOffset(offset); 3178fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 317958ae9c530247668f8af36e30d228c716c226b3d4James Dong } 318058ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 318158ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 318258ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 318358ae9c530247668f8af36e30d228c716c226b3d4James Dong } 318413aec890216948b0c364f8f92792129d0335f506James Dong 318513aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 3186fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mIsHeic) { 3187fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang bufferChunk(0 /*timestampUs*/); 3188fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ++nChunks; 3189fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else if (interleaveDurationUs == 0) { 31901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 31911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 319213aec890216948b0c364f8f92792129d0335f506James Dong } else { 319313aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 319413aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 319513aec890216948b0c364f8f92792129d0335f506James Dong } else { 319643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 319743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 319843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 319943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 320043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 320113aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 320213aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 3203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 3204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 3205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 320613aec890216948b0c364f8f92792129d0335f506James Dong } 32071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 320813aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 320913aec890216948b0c364f8f92792129d0335f506James Dong } 321013aec890216948b0c364f8f92792129d0335f506James Dong } 321113aec890216948b0c364f8f92792129d0335f506James Dong } 321213aec890216948b0c364f8f92792129d0335f506James Dong 321320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 321425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 321545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 321662a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang dumpTimeStamps(); 3217690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 3218f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 321945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 3220bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 3221be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 3222fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mIsHeic) { 3223fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!mChunkSamples.empty()) { 3224fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang bufferChunk(0); 3225fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ++nChunks; 3226fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 3227be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 3228fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // Last chunk 3229fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!hasMultipleTracks) { 3230fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang addOneStscTableEntry(1, mStszTableEntries->count()); 3231fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else if (!mChunkSamples.empty()) { 3232fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang addOneStscTableEntry(++nChunks, mChunkSamples.size()); 3233fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang bufferChunk(timestampUs); 3234fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 3235a472613aec322e25891abf5c77bf3f7e3c244920James Dong 3236fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // We don't really know how long the last frame lasts, since 3237fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // there is no frame time after it, just repeat the previous 3238fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // frame's duration. 3239fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mStszTableEntries->count() == 1) { 3240fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang lastDurationUs = 0; // A single sample's duration 3241fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang lastDurationTicks = 0; 3242fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else { 3243fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ++sampleCount; // Count for the last sample 3244fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 3245fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 3246fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mStszTableEntries->count() <= 2) { 3247fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang addOneSttsTableEntry(1, lastDurationTicks); 3248fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (sampleCount - 1 > 0) { 3249fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 3250fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 3251fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else { 3252fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang addOneSttsTableEntry(sampleCount, lastDurationTicks); 3253a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 3254a472613aec322e25891abf5c77bf3f7e3c244920James Dong 3255fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // The last ctts box may not have been written yet, and this 3256fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // is to make sure that we write out the last ctts box. 3257fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 3258fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (cttsSampleCount > 0) { 3259fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 3260fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 326143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 326243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 3263fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mTrackDurationUs += lastDurationUs; 3264fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 326525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 326643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 326743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 326843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 3269df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 327011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih count, nZeroLengthFrames, mStszTableEntries->count(), trackName); 3271872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 3272a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs()); 3273872a481558350634a3fd5cb67939de288af00ecbJames Dong } 3274365a963142093a1cd8efdcea76b5f65096a5b115James Dong 327537187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 327637187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 327737187916a486504acaf83bea30147eb5fbf46ae5James Dong } 327837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 3279365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 3280365a963142093a1cd8efdcea76b5f65096a5b115James Dong 328145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 32829db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang if (mIsMalformed) { 32839db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang return true; 32849db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang } 32859db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang 3286fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!mIsHeic && mStszTableEntries->count() == 0) { // no samples written 328729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 328845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 328945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 329045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 329125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo && mStssTableEntries->count() == 0) { // no sync frames for video 329229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 329345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 329445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 329545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 329645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 329745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 329845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 329945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 330045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 330145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 330245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 330343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 330407ec01904613a0bac32caaa8444b4690998faed7James Dong 330507ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 330607ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 330707ec01904613a0bac32caaa8444b4690998faed7James Dong return; 330807ec01904613a0bac32caaa8444b4690998faed7James Dong } 330907ec01904613a0bac32caaa8444b4690998faed7James Dong 331043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 331143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 331243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 331343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 331425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mIsAudio ? 0: 1); 331543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 331643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 331743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 331843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 331943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 332043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 332143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 3322c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 332343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 332486b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 332586b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 332686b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 332786b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 332886b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 332986b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 333086b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 333186b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 333286b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 333386b7f47aa7482424cf8fd248f1315311919be3b0James Dong 333486b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 333570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 333670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 333786b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 333870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 333907ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 334007ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 334107ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 334207ec01904613a0bac32caaa8444b4690998faed7James Dong 334343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 334443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 334543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 334643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 334770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 334870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 334970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 335070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 335170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 335270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 335370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 335470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 335543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 335643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 335743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 3358faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 3359a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("trackProgressStatus: %" PRId64 " us", timeUs); 3360c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 3361215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 3362215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 3363a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs); 3364bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 336593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 336693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 336793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 336893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 3369faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 3370bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 3371faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 3372bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 3373faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 3374faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 3375faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 3376faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 3377bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 3378bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 3379faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 3380faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 3381faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 3382faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 3383faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 3384faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 3385bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3386bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 3387faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 3388faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 3389faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 3390bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3391bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 3392faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 3393faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 3394faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 3395faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 3396d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 3397a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs); 3398e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 3399d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 3400e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 3401e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 3402e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 3403a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs); 3404e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 3405e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 3406e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 3407e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 3408de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const { 3409de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui return mIsRealTimeRecording; 3410de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui} 3411de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 3412b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 3413b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 3414b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 3415b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 34161c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 34173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 34181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 34191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 34201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 342113aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 342220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 342320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 34243b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 3425230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang return mTrackDurationUs + getStartTimeOffsetTimeUs(); 342620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 342720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3428d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 3429d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 3430d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 3431d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 3432fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangint32_t MPEG4Writer::Track::getMetaSizeIncrease() const { 3433fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang CHECK(mIsHeic); 3434fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang return 20 // 1. 'ispe' property 3435fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + (8 + mCodecSpecificDataSize) // 2. 'hvcC' property 3436fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + (20 // 3. extra 'ispe' 3437fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + (8 + 2 + 2 + mNumTiles * 2) // 4. 'dimg' ref 3438fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + 12) // 5. ImageGrid in 'idat' (worst case) 3439fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang * (mNumTiles > 1) // - (3~5: applicable only if grid) 3440fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + (16 // 6. increase to 'iloc' 3441fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + 21 // 7. increase to 'iinf' 3442fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang + (3 + 2 * 2)) // 8. increase to 'ipma' (worst case) 3443fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang * (mNumTiles + 1); // - (6~8: are per-item) 3444fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 3445fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 3446690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 3447690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 3448690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 3449690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 3450690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 34519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) || 3452fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime) || 3453fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang !strcasecmp(MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, mime)) { 3454690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 3455690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 345629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 3457690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 3458690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 3459690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 3460690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 3461690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 346229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 3463690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 3464690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 3465690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 3466690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 3467690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 3468690f546b0ee548dbfe997df36418e5302ec2d786James Dong 346925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangconst char *MPEG4Writer::Track::getTrackType() const { 3470fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang return mIsAudio ? "Audio" : 3471fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mIsVideo ? "Video" : 3472fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mIsHeic ? "Image" : 3473fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang "Metadata"; 347425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang} 34758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 347625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 3477efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 3478b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 3479b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 3480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 3481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 3482b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 3483b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 3484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 3485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 348625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (mIsVideo) { 3487b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 348825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else { 348925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang writeNmhdBox(); 3490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 3492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 3493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 3494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 3495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 3496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3498230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuangint64_t MPEG4Writer::Track::getMinCttsOffsetTimeUs() { 3499230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang // For video tracks with ctts table, this should return the minimum ctts 3500230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang // offset in the table. For non-video tracks or video tracks without ctts 3501230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang // table, this will return kMaxCttsOffsetTimeUs. 3502230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) { 3503230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang return kMaxCttsOffsetTimeUs; 3504230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang } 3505230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang return mMinCttsOffsetTimeUs; 3506230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang} 3507230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang 3508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 3509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 3510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 3511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 3513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 3514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 351525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (mIsVideo) { 3516b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 351725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else { 351825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang writeMetadataFourCCBox(); 3519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 3521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 352225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo) { 352325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang writeCttsBox(); 3524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 3525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 3527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 3528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 3529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 3530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 353225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeMetadataFourCCBox() { 353325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *mime; 353425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang bool success = mMeta->findCString(kKeyMIMEType, &mime); 353525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang CHECK(success); 353625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *fourcc = getFourCCForMime(mime); 353725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (fourcc == NULL) { 353825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("Unknown mime type '%s'.", mime); 353925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang TRESPASS(); 354025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } 354125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->beginBox(fourcc); // TextMetaDataSampleEntry 354225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeCString(mime); // metadata mime_format 354325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->endBox(); // mett 354425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang} 354525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang 3546b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 3547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 3548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 3549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 35508b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 35518b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 355229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 355325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang TRESPASS(); 3554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 35568b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan mOwner->beginBox(fourcc); // video format 3557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3558b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 3560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3561b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 3563b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 3564b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 3565b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 3567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 3568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 3569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 3572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 3573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 3574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 3575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 3577c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->writeInt8(0); // compressor string length 3578c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->write(" ", 31); 3579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 3580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 3581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 3583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 3584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 3585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 3586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 3587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 35889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 35899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim writeHvccBox(); 3590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3591b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 359358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar writeColrBox(); 3594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 3595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 359758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() { 359858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar ColorAspects aspects; 359958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar memset(&aspects, 0, sizeof(aspects)); 360058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar // TRICKY: using | instead of || because we want to execute all findInt32-s 360158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries) 360258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer) 360358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs) 360458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) { 360558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar int32_t primaries, transfer, coeffs; 360658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar bool fullRange; 360758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar ColorUtils::convertCodecColorAspectsToIsoAspects( 360858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar aspects, &primaries, &transfer, &coeffs, &fullRange); 360958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->beginBox("colr"); 361058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeFourcc("nclx"); 361158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(primaries); 361258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(transfer); 361358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(coeffs); 3614fffb0c8fbe16ac948619b85e1eea9e65a9daa0c9Pirama Arumuga Nainar mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0)); 361558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->endBox(); // colr 361658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar } 361758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar} 361858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar 3619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 3620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 3621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 3622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 36238b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 36248b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 362529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 362625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang TRESPASS(); 3627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 3630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 3633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 3636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 3637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 3638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 3639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 3643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 3644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 3646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 3647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 3648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 3649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 3650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 3651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 3656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 3657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 3658b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_GT(mCodecSpecificDataSize, 0u); 3659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 3661b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_LT(mCodecSpecificDataSize + 23, 128u); 3662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 3665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 3666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 3667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 3668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 3671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 3672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 3673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 367546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt8(0x00); // buffer size 24-bit (0x300) 367646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 367796bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t avgBitrate = 0; 367846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 367996bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t maxBitrate = 0; 368046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 368146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(maxBitrate); 368246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(avgBitrate); 3683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 3686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 3689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 3690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 3691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 3692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 3694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 3696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3698b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 3699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 3700b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_GT(mCodecSpecificDataSize, 0u); 3701bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan 3702bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan // Make sure all sizes encode to a single byte. 3703b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_LT(23 + mCodecSpecificDataSize, 128u); 3704bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan 3705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 3706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 3710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 3711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 3712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 3713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 3716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 3717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 3718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 372046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 0x01, 0x77, 0x00, // buffer size 96000 bytes 3721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 3723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 372496bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t avgBitrate = 0; 372546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 372696bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t maxBitrate = 0; 372746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 372846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(maxBitrate); 372946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(avgBitrate); 373046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 3731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 3734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 3737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 3738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 3739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 3740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 3742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 3744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3746efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 3747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 3748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 3749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 3750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 3751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 3752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 3753219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 3754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 37558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 3756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 3757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 3758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 3759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 3760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 3763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 3764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 3765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 376820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 376925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (!mIsVideo) { 3770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 3771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 3772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 3773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 3774467743d462773ada299148ed5a210479affd1f4cHangyu Kuang bool success = mMeta->findInt32(kKeyDisplayWidth, &width); 3775467743d462773ada299148ed5a210479affd1f4cHangyu Kuang success = success && mMeta->findInt32(kKeyDisplayHeight, &height); 3776467743d462773ada299148ed5a210479affd1f4cHangyu Kuang 3777467743d462773ada299148ed5a210479affd1f4cHangyu Kuang // Use width/height if display width/height are not present. 3778467743d462773ada299148ed5a210479affd1f4cHangyu Kuang if (!success) { 3779467743d462773ada299148ed5a210479affd1f4cHangyu Kuang success = mMeta->findInt32(kKeyWidth, &width); 3780467743d462773ada299148ed5a210479affd1f4cHangyu Kuang success = success && mMeta->findInt32(kKeyHeight, &height); 3781467743d462773ada299148ed5a210479affd1f4cHangyu Kuang } 3782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 3785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 3786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 3788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 3791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 3792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 3793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 3794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 3795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 3796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 3797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 3801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 3802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 3804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 380825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeNmhdBox() { 380925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->beginBox("nmhd"); 381025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeInt32(0); // version=0, flags=0 381125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->endBox(); 381225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang} 381325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang 3814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 3815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 3816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 381825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeFourcc(mIsAudio ? "soun" : (mIsVideo ? "vide" : "meta")); // component subtype 3819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 382325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeCString(mIsAudio ? "SoundHandle": (mIsVideo ? "VideoHandle" : "MetadHandle")); 3824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3827efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 3828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 38291d515f4b608f1e6592780365857855962c0da725xiahong.bao int64_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 3830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 38311d515f4b608f1e6592780365857855962c0da725xiahong.bao 38321d515f4b608f1e6592780365857855962c0da725xiahong.bao if (mdhdDuration > UINT32_MAX) { 38331d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32((1 << 24)); // version=1, flags=0 38341d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt64((int64_t)now); // creation time 38351d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt64((int64_t)now); // modification time 38361d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32(mTimeScale); // media timescale 38371d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt64(mdhdDuration); // media timescale 38381d515f4b608f1e6592780365857855962c0da725xiahong.bao } else { 38391d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32(0); // version=0, flags=0 38401d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32(now); // creation time 38411d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32(now); // modification time 38421d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32(mTimeScale); // media timescale 38431d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32((int32_t)mdhdDuration); // use media timescale 38441d515f4b608f1e6592780365857855962c0da725xiahong.bao } 3845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 3846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 3847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 3848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 3849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 3850decc50efede28c5d73137c30d1a95d72dd405555David Yeh const char *lang = NULL; 3851decc50efede28c5d73137c30d1a95d72dd405555David Yeh int16_t langCode = 0; 3852decc50efede28c5d73137c30d1a95d72dd405555David Yeh if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) { 3853decc50efede28c5d73137c30d1a95d72dd405555David Yeh langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f); 3854decc50efede28c5d73137c30d1a95d72dd405555David Yeh } 3855decc50efede28c5d73137c30d1a95d72dd405555David Yeh mOwner->writeInt16(langCode); // language code 3856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 3861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 3862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 3863b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 3864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 3866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 3867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 3868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 3872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 3873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 3874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 3875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 3876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 3877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 3880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 3881b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 3883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 3884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 3885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 3888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 3889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 3890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 3891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 3894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 3895b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_GE(mCodecSpecificDataSize, 5u); 3896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 3898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 3899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 3900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 3901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 3902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 3904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 39069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 39079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() { 39089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim CHECK(mCodecSpecificData); 3909b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross CHECK_GE(mCodecSpecificDataSize, 5u); 39109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 39119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Patch avcc's lengthSize field to match the number 39129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // of bytes we use to indicate the size of a nal unit. 39139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim uint8_t *ptr = (uint8_t *)mCodecSpecificData; 39149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 39159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->beginBox("hvcC"); 39169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 39179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->endBox(); // hvcC 39189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 39199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 3920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 3921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 3922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 3923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 3925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 3926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 3927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 3930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 3931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 3932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 3933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 3934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 3935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3937230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuangint64_t MPEG4Writer::Track::getStartTimeOffsetTimeUs() const { 3938a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 3939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3940a9292fe1c19e8a9b43398ba3d69284c215d7589fRobert Shih if (mStartTimestampUs != -1 && mStartTimestampUs != moovStartTimeUs) { 394143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 3942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 39446a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih return trackStartTimeOffsetUs; 39456a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih} 39466a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shih 39476a5c19cae5b1958af824f349a5c3778255ecd9c7Robert Shihint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 3948230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang return (getStartTimeOffsetTimeUs() * mTimeScale + 500000LL) / 1000000LL; 3949000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 3950000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3951000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 3952000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 3953000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3954230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) { 3955230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang // For non-vdeio tracks or video tracks without ctts table, 3956230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang // adjust duration of first sample for tracks to account for 3957230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang // first sample not starting at the media start time. 3958230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang // TODO: consider signaling this using some offset 3959230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang // as this is not quite correct. 3960230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang uint32_t duration; 3961230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang CHECK(mSttsTableEntries->get(duration, 1)); 3962230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang duration = htonl(duration); // Back to host byte order 3963230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 3964230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang } 3965c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 3966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 3967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 396820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3969965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 3970000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 3971230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) { 3972000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 3973000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 3974000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3975965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 3976c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 3977965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3978965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3979965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3980a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]", 3981230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang mCttsTableEntries->count(), mMinCttsOffsetTicks, mMaxCttsOffsetTicks); 3982965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3983965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 3984000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3985230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang int64_t deltaTimeUs = kMaxCttsOffsetTimeUs - getStartTimeOffsetTimeUs(); 3986230b680d02e32898d90bddabe27295b753f9fbb3Hangyu Kuang int64_t delta = (deltaTimeUs * mTimeScale + 500000LL) / 1000000LL; 3987c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) { 3988c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar // entries are <count, ctts> pairs; adjust only ctts 3989c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t duration = htonl(value[1]); // back to host byte order 39900d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka // Prevent overflow and underflow 39910d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka if (delta > duration) { 39920d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka duration = 0; 39930d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka } else if (delta < 0 && UINT32_MAX + delta < duration) { 39940d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka duration = UINT32_MAX; 39950d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka } else { 39960d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka duration -= delta; 39970d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka } 39980d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka value[1] = htonl(duration); 3999c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar }); 4000c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 4001965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 4002965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 4003965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 4004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 4005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 4006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 4007c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 4008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 4009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 401025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 4011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 4012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 4013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 4014c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 4015c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 4016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 4017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 401820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 4020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 4021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 4022c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 4023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 4024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 402520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 4027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 4028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 4029c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 4030c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 4031c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 4032c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 4033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 4034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 403520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 403620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 403707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 403807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 403907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 404007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 404107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 404207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 4043fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeHdlr(const char *handlerType) { 4044e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("hdlr"); 4045e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 4046e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Predefined 4047fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeFourcc(handlerType); 4048e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[0] 4049e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[1] 4050e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[2] 4051e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt8(0); // Name (empty) 4052e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 4053e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 4054e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 4055e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() { 4056e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 4057e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 4058e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("keys"); 4059e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 4060e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(count); // Entry_count 4061e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 4062e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 4063e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 4064e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t n = strlen(key); 4065e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(n + 8); 4066e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 4067e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang write(key, n); // write without the \0 4068e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 4069e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 4070e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 4071e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 4072e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() { 4073e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 4074e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 4075e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("ilst"); 4076e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 4077e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox(i + 1); // key id (1-based) 4078e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("data"); 4079e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 4080e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 4081e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang switch (type) { 40827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang case AMessage::kTypeString: 40837c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang { 40847c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang AString val; 40857c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang CHECK(mMetaKeys->findString(key, &val)); 40867c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(1); // type = UTF8 40877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 40887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang write(val.c_str(), strlen(val.c_str())); // write without \0 40897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang break; 40907c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 40917c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 4092e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeFloat: 4093e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 4094e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang float val; 4095e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findFloat(key, &val)); 40967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(23); // type = float32 40977c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 4098e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(*reinterpret_cast<int32_t *>(&val)); 4099e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 4100e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 4101e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 4102e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeInt32: 4103e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 4104e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang int32_t val; 4105e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findInt32(key, &val)); 41067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(67); // type = signed int32 41077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 4108e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(val); 4109e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 4110e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 4111e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 4112e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang default: 4113e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 4114e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang ALOGW("Unsupported key type, writing 0 instead"); 41157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(77); // type = unsigned int32 41167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 4117e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 4118e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 4119e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 4120e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 4121e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // data 4122e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // key id 4123e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 4124e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // ilst 4125e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 4126e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 4127fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeMoovLevelMetaBox() { 4128e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 4129e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (count == 0) { 4130e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return; 4131e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 4132e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 4133e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("meta"); 4134fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeHdlr("mdta"); 4135e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeKeys(); 4136e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeIlst(); 4137e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 4138e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 4139e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 4140fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIlocBox() { 4141fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("iloc"); 4142fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // Use version 1 to allow construction method 1 that refers to 4143fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // data in idat box inside meta box. 4144fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(0x01000000); // Version = 1, Flags = 0 4145fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16(0x4400); // offset_size = length_size = 4 4146fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // base_offset_size = index_size = 0 4147fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4148fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // 16-bit item_count 4149fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang size_t itemCount = mItems.size(); 4150fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (itemCount > 65535) { 4151fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGW("Dropping excess items: itemCount %zu", itemCount); 4152fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang itemCount = 65535; 4153fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4154fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16((uint16_t)itemCount); 4155fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4156fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang for (size_t i = 0; i < itemCount; i++) { 4157fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16(mItems[i].itemId); 4158fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang bool isGrid = mItems[i].isGrid(); 4159fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4160fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16(isGrid ? 1 : 0); // construction_method 4161fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16(0); // data_reference_index = 0 4162fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16(1); // extent_count = 1 4163fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4164fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (isGrid) { 4165fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // offset into the 'idat' box 4166fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(mNumGrids++ * 8); 4167fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(8); 4168fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else { 4169fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(mItems[i].offset); 4170fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(mItems[i].size); 4171fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4172fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4173fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4174fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 4175fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4176fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeInfeBox( 4177fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang uint16_t itemId, const char *itemType, uint32_t flags) { 4178fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("infe"); 4179fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(0x02000000 | flags); // Version = 2, Flags = 0 4180fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16(itemId); 4181fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16(0); //item_protection_index = 0 4182fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeFourcc(itemType); 4183fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeCString(""); // item_name 4184fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4185fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 4186fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4187fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIinfBox() { 4188fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("iinf"); 4189fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(0); // Version = 0, Flags = 0 4190fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4191fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // 16-bit item_count 4192fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang size_t itemCount = mItems.size(); 4193fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (itemCount > 65535) { 4194fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGW("Dropping excess items: itemCount %zu", itemCount); 4195fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang itemCount = 65535; 4196fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4197fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4198fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16((uint16_t)itemCount); 4199fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang for (size_t i = 0; i < itemCount; i++) { 4200fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInfeBox(mItems[i].itemId, mItems[i].itemType, 4201fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mItems[i].isHidden ? 1 : 0); 4202fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4203fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4204fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4205fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 4206fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4207fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIdatBox() { 4208fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("idat"); 4209fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4210fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang for (size_t i = 0; i < mItems.size(); i++) { 4211fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mItems[i].isGrid()) { 4212fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt8(0); // version 4213fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // flags == 1 means 32-bit width,height 4214fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang int8_t flags = (mItems[i].width > 65535 || mItems[i].height > 65535); 4215fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt8(flags); 4216fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt8(mItems[i].rows - 1); 4217fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt8(mItems[i].cols - 1); 4218fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (flags) { 4219fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(mItems[i].width); 4220fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(mItems[i].height); 4221fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else { 4222fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16((uint16_t)mItems[i].width); 4223fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16((uint16_t)mItems[i].height); 4224fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4225fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4226fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4227fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4228fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4229fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 4230fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4231fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIrefBox() { 4232fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("iref"); 4233fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(0); // Version = 0, Flags = 0 4234fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang { 4235fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang for (size_t i = 0; i < mItems.size(); i++) { 4236fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!mItems[i].isGrid()) { 4237fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang continue; 4238fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4239fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("dimg"); 4240fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16(mItems[i].itemId); 4241fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang size_t refCount = mItems[i].dimgRefs.size(); 4242fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (refCount > 65535) { 4243fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGW("too many entries in dimg"); 4244fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang refCount = 65535; 4245fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4246fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16((uint16_t)refCount); 4247fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang for (size_t refIndex = 0; refIndex < refCount; refIndex++) { 4248fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16(mItems[i].dimgRefs[refIndex]); 4249fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4250fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4251fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4252fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4253fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4254fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 4255fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4256fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writePitmBox() { 4257fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("pitm"); 4258fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(0); // Version = 0, Flags = 0 4259fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16(mPrimaryItemId); 4260fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4261fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 4262fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4263fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIpcoBox() { 4264fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("ipco"); 4265fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang size_t numProperties = mProperties.size(); 4266fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (numProperties > 32767) { 4267fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGW("Dropping excess properties: numProperties %zu", numProperties); 4268fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang numProperties = 32767; 4269fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4270fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang for (size_t propIndex = 0; propIndex < numProperties; propIndex++) { 4271fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mProperties[propIndex].type == FOURCC('h', 'v', 'c', 'C')) { 4272fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("hvcC"); 4273fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang sp<ABuffer> hvcc = mProperties[propIndex].hvcc; 4274fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // Patch avcc's lengthSize field to match the number 4275fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // of bytes we use to indicate the size of a nal unit. 4276fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang uint8_t *ptr = (uint8_t *)hvcc->data(); 4277fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ptr[21] = (ptr[21] & 0xfc) | (useNalLengthFour() ? 3 : 1); 4278fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang write(hvcc->data(), hvcc->size()); 4279fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4280fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else if (mProperties[propIndex].type == FOURCC('i', 's', 'p', 'e')) { 4281fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("ispe"); 4282fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(0); // Version = 0, Flags = 0 4283fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(mProperties[propIndex].width); 4284fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(mProperties[propIndex].height); 4285fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4286fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else { 4287fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGW("Skipping unrecognized property: type 0x%08x", 4288fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mProperties[propIndex].type); 4289fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4290fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4291fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4292fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 4293fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4294fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIpmaBox() { 4295fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("ipma"); 4296fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang uint32_t flags = (mProperties.size() > 127) ? 1 : 0; 4297fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(flags); // Version = 0 4298fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4299fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(mAssociationEntryCount); 4300fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang for (size_t itemIndex = 0; itemIndex < mItems.size(); itemIndex++) { 4301fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang const Vector<uint16_t> &properties = mItems[itemIndex].properties; 4302fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (properties.empty()) { 4303fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang continue; 4304fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4305fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16(mItems[itemIndex].itemId); 4306fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4307fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang size_t entryCount = properties.size(); 4308fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (entryCount > 255) { 4309fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGW("Dropping excess associations: entryCount %zu", entryCount); 4310fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang entryCount = 255; 4311fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4312fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt8((uint8_t)entryCount); 4313fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang for (size_t propIndex = 0; propIndex < entryCount; propIndex++) { 4314fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (flags & 1) { 4315fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt16((1 << 15) | properties[propIndex]); 4316fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } else { 4317fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt8((1 << 7) | properties[propIndex]); 4318fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4319fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4320fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4321fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4322fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 4323fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4324fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeIprpBox() { 4325fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("iprp"); 4326fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeIpcoBox(); 4327fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeIpmaBox(); 4328fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4329fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 4330fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4331fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhangvoid MPEG4Writer::writeFileLevelMetaBox() { 4332fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mItems.empty()) { 4333fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGE("no valid item was found"); 4334fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang return; 4335fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4336fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4337fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // patch up the mPrimaryItemId and count items with prop associations 4338fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang for (size_t index = 0; index < mItems.size(); index++) { 4339fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mItems[index].isPrimary) { 4340fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mPrimaryItemId = mItems[index].itemId; 4341fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4342fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4343fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!mItems[index].properties.empty()) { 4344fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mAssociationEntryCount++; 4345fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4346fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4347fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4348fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mPrimaryItemId == 0) { 4349fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGW("didn't find primary, using first item"); 4350fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mPrimaryItemId = mItems[0].itemId; 4351fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4352fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4353fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang beginBox("meta"); 4354fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeInt32(0); // Version = 0, Flags = 0 4355fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeHdlr("pict"); 4356fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeIlocBox(); 4357fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeIinfBox(); 4358fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writePitmBox(); 4359fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeIprpBox(); 4360fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (mNumGrids > 0) { 4361fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeIdatBox(); 4362fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang writeIrefBox(); 4363fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4364fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang endBox(); 4365fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 4366fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4367fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhanguint16_t MPEG4Writer::addProperty_l(const ItemProperty &prop) { 4368fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang char typeStr[5]; 4369fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang MakeFourCCString(prop.type, typeStr); 4370fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGV("addProperty_l: %s", typeStr); 4371fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4372fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mProperties.push_back(prop); 4373fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4374fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // returning 1-based property index 4375fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang return mProperties.size(); 4376fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 4377fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4378fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhanguint16_t MPEG4Writer::addItem_l(const ItemInfo &info) { 4379fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGV("addItem_l: type %s, offset %u, size %u", 4380fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang info.itemType, info.offset, info.size); 4381fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4382fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang size_t index = mItems.size(); 4383fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mItems.push_back(info); 4384fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4385fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang // make the item id start at 10000 4386fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang mItems.editItemAt(index).itemId = index + 10000; 4387fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4388fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang#if (LOG_NDEBUG==0) 4389fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (!info.properties.empty()) { 4390fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang AString str; 4391fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang for (size_t i = 0; i < info.properties.size(); i++) { 4392fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang if (i > 0) { 4393fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang str.append(", "); 4394fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4395fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang str.append(info.properties[i]); 4396fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4397fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang ALOGV("addItem_l: id %d, properties: %s", mItems[index].itemId, str.c_str()); 4398fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang } 4399fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang#endif // (LOG_NDEBUG==0) 4400fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 4401fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang return mItems[index].itemId; 4402fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang} 4403fbc97c5266ec4e9fbe98db944f7aa99452299ae8Chong Zhang 440407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 440507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 440607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 440707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 440807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 440907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 441007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 441107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 441207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 4413432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 4414432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 441507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 441607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 441707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 441807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 441907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 442007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 442107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 442207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 442320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 4424