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