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 3543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong#include <media/stagefright/foundation/ADebug.h> 36e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang#include <media/stagefright/foundation/AMessage.h> 37826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar#include <media/stagefright/foundation/AUtils.h> 3858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar#include <media/stagefright/foundation/ColorUtils.h> 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 4218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 4303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h> 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 46d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h> 4707ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h> 4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h" 509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include "include/HevcUtils.h" 5180f78b773f92048944a850efb7b60629643370cdPraveen Chavan#include "include/avc_utils.h" 52dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn 53dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false 54dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0) 55dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif 56dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn 5711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \ 58dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \ 5911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih ALOGW("Condition %s failed " message, #condition, ##__VA_ARGS__); \ 6011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih true; \ 6111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih})) 6211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6577e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024; 661f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32 671f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad // filesystem file size 681f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad // used by most SD cards 693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07; 703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08; 7170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs = 700000LL; 72e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuangstatic const int64_t kMaxMetadataSize = 0x4000000LL; // 64MB max per-frame metadata size 735b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong 747c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[] = "com.android.version"; 75da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuangstatic const char kMetaKey_Manufacturer[] = "com.android.manufacturer"; 763b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[] = "com.android.model"; 77da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang 78da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang#ifdef SHOW_BUILD 797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[] = "com.android.build"; 803b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif 817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps"; 824dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatic const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count"; 837c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 8462a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuangstatic const int kTimestampDebugCount = 10; 8562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang 869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = { 879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeVps, 889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeSps, 899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypePps, 909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}; 919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = { 929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeVps, 939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeSps, 949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypePps, 959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypePrefixSei, 969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeSuffixSei, 979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}; 98da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang/* uncomment to include build in meta */ 997c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1 1007c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 103b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen Track(MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId); 1048f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 108fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang status_t stop(bool stopSource = true); 10937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 11025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1123b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 113d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTrackHeader(bool use32BitOffset = true); 1151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 1161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 1179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bool isHevc() const { return mIsHevc; } 1181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 1191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 120c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong void addChunkOffset(off64_t offset); 12170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int32_t getTrackId() const { return mTrackId; } 122dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 1238b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan static const char *getFourCCForMime(const char *mime); 12425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *getTrackType() const; 125fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang void resetInternal(); 12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 128000e18370baae60ffd9f25b509501dd8c26deabfJames Dong enum { 129000e18370baae60ffd9f25b509501dd8c26deabfJames Dong kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 1308c460498c028888c533ab442be12b6d4b669b965James Dong kSampleArraySize = 1000, 131000e18370baae60ffd9f25b509501dd8c26deabfJames Dong }; 132000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // A helper class to handle faster write box with table entries 134c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar template<class TYPE, unsigned ENTRY_SIZE> 135c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar // ENTRY_SIZE: # of values in each entry 136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong struct ListTableEntries { 137c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar static_assert(ENTRY_SIZE > 0, "ENTRY_SIZE must be positive"); 138c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries(uint32_t elementCapacity) 139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mElementCapacity(elementCapacity), 140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTotalNumTableEntries(0), 141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry(0), 142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement(NULL) { 143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mElementCapacity, 0); 1442177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia // Ensure no integer overflow on allocation in add(). 145c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar CHECK_LT(ENTRY_SIZE, UINT32_MAX / mElementCapacity); 146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Free the allocated memory. 149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ~ListTableEntries() { 150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (!mTableEntryList.empty()) { 151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete[] (*it); 153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.erase(it); 154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Replace the value at the given position by the given value. 158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // There must be an existing value at the given position. 159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order 160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void set(const TYPE& value, uint32_t pos) { 162c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar CHECK_LT(pos, mTotalNumTableEntries * ENTRY_SIZE); 163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 165c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE)); 166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 173c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar (*it)[(pos % (mElementCapacity * ENTRY_SIZE))] = value; 174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Get the value at the given position by the given value. 177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value the retrieved value at the position in network byte order. 178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @return true if a value is found. 180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool get(TYPE& value, uint32_t pos) const { 181c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar if (pos >= mTotalNumTableEntries * ENTRY_SIZE) { 182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return false; 183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 186c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE)); 187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 194c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar value = (*it)[(pos % (mElementCapacity * ENTRY_SIZE))]; 195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return true; 196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 198c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar // adjusts all values by |adjust(value)| 199c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar void adjustEntries( 200c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar std::function<void(size_t /* ix */, TYPE(& /* entry */)[ENTRY_SIZE])> update) { 201c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar size_t nEntries = mTotalNumTableEntries + mNumValuesInCurrEntry / ENTRY_SIZE; 202c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar size_t ix = 0; 203c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar for (TYPE *entryArray : mTableEntryList) { 204c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar size_t num = std::min(nEntries, (size_t)mElementCapacity); 205c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar for (size_t i = 0; i < num; ++i) { 206c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar update(ix++, (TYPE(&)[ENTRY_SIZE])(*entryArray)); 207c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar entryArray += ENTRY_SIZE; 208c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar } 209c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar nEntries -= num; 210c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar } 211c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar } 212c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar 213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Store a single value. 214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order. 215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void add(const TYPE& value) { 216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 218c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t nValues = mNumValuesInCurrEntry % ENTRY_SIZE; 219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries == 0 && nValues == 0) { 220c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCurrTableEntriesElement = new TYPE[ENTRY_SIZE * mElementCapacity]; 221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCurrTableEntriesElement != NULL); 222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.push_back(mCurrTableEntriesElement); 223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 225c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t pos = nEntries * ENTRY_SIZE + nValues; 226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement[pos] = value; 227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mNumValuesInCurrEntry; 229c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar if ((mNumValuesInCurrEntry % ENTRY_SIZE) == 0) { 230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mTotalNumTableEntries; 231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry = 0; 232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 235c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Write out the table entries: 236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 1. the number of entries goes first 237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 2. followed by the values in the table enties in order 238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg writer the writer to actual write to the storage 239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void write(MPEG4Writer *writer) const { 240c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar CHECK_EQ(mNumValuesInCurrEntry % ENTRY_SIZE, 0); 241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries; 242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->writeInt32(nEntries); 243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong it != mTableEntryList.end(); ++it) { 245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(nEntries, 0); 246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries >= mElementCapacity) { 247c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, mElementCapacity); 248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong nEntries -= mElementCapacity; 249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 250c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, nEntries); 251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong break; 252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 256c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Return the number of entries in the table. 257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count() const { return mTotalNumTableEntries; } 258c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong private: 260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mElementCapacity; // # entries in an element 261c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mTotalNumTableEntries; 262c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t mNumValuesInCurrEntry; // up to ENTRY_SIZE 263c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong TYPE *mCurrTableEntriesElement; 264c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mutable List<TYPE *> mTableEntryList; 265c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 267c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong }; 268c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 269c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 270c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 273b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen sp<IMediaSource> mSource; 27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 275a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 276a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 277eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 2781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 2799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bool mIsHevc; 2801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 28125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang bool mIsVideo; 2821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 283fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang bool mGotStartKeyFrame; 2849db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang bool mIsMalformed; 285bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 286c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 28743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 288826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar int64_t mLastDecodingTimeUs; 289e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 290d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 2911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 2928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 296be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 29713aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 2981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 299c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool mSamplesHaveSameSize; 300c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 1> *mStszTableEntries; 301be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 302c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 1> *mStcoTableEntries; 303c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<off64_t, 1> *mCo64TableEntries; 304c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 3> *mStscTableEntries; 305c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 1> *mStssTableEntries; 306c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 2> *mSttsTableEntries; 307c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 2> *mCttsTableEntries; 308965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 309000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMinCttsOffsetTimeUs; 310000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMaxCttsOffsetTimeUs; 311965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 31262a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang // Save the last 10 frames' timestamp for debug. 31362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang std::list<std::pair<int64_t, int64_t>> mTimestampDebugHelper; 31462a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang 3153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 3163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 3173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 3183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 3193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 3203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 3213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 3223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 3233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 3243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 3253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 3263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 3273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 3283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 331548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 33293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 3353c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 33670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 33770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 33893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 33993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 34025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 341872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 342872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 343872a481558350634a3fd5cb67939de288af00ecbJames Dong 34462a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang void dumpTimeStamps(); 34562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang 346000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int32_t getStartTimeOffsetScaledTime() const; 347000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 34937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 3523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 3533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 3549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0); 3559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 359215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 3609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size); 3619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size); 3629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t parseHEVCCodecSpecificData( 3639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, HevcParameterSets ¶mSets); 3649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 365215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 366faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 36793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 36803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 36919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 37019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 371c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 372c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 373c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 374c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 375c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 376c059860c73678a202bfa33062723e8f82fb779d9James Dong 377690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 378690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 37913f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t mRotation; 380690f546b0ee548dbfe997df36418e5302ec2d786James Dong 3811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 3821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 3831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 38479761ab096f57c3027fad9556c2bc436672d614eJames Dong 38579761ab096f57c3027fad9556c2bc436672d614eJames Dong // Duration is time scale based 38679761ab096f57c3027fad9556c2bc436672d614eJames Dong void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 387965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 38845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 38945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong bool isTrackMalFormed() const; 39043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 3911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 398965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void writeCttsBox(); 399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 4029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim void writeHvccBox(); 403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 407efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeMdhdBox(uint32_t now); 408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 41025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang void writeNmhdBox(); 411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 412efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeTkhdBox(uint32_t now); 41358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar void writeColrBox(); 414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 41825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang void writeMetadataFourCCBox(); 419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 425fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu KuangMPEG4Writer::MPEG4Writer(int fd) { 426fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang initInternal(fd); 42730ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 42830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 42920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 4308bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong reset(); 43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 4331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 4351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 4361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 439fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 440fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mNextFd != -1) { 441fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang close(mNextFd); 442fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 443fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 444fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 445fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::initInternal(int fd) { 446fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGV("initInternal"); 4478fdb3fde346b446ad3b04dafa65a6844da672e23Hangyu Kuang mFd = dup(fd); 448fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mNextFd = -1; 449fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mInitCheck = mFd < 0? NO_INIT: OK; 450fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mIsRealTimeRecording = true; 451fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mUse4ByteNalLength = true; 452fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mUse32BitOffset = true; 453fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mIsFileSizeLimitExplicitlyRequested = false; 454fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mPaused = false; 455fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStarted = false; 456fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mWriterThreadStarted = false; 457fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSendNotify = false; 458fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mOffset = 0; 459fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMdatOffset = 0; 460fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMoovBoxBuffer = NULL; 461fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMoovBoxBufferOffset = 0; 462fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mWriteMoovBoxToMemory = false; 463fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mFreeBoxOffset = 0; 464fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStreamableFile = false; 465fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mEstimatedMoovBoxSize = 0; 466fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMoovExtraSize = 0; 467fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mInterleaveDurationUs = 1000000; 468fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mTimeScale = -1; 469fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStartTimestampUs = -1ll; 470fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLatitudex10000 = 0; 471fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLongitudex10000 = 0; 472fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mAreGeoTagsAvailable = false; 473fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStartTimeOffsetMs = -1; 474fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSwitchPending = false; 475fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMetaKeys = new AMessage(); 476fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang addDeviceMeta(); 477fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // Verify mFd is seekable 478fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang off64_t off = lseek64(mFd, 0, SEEK_SET); 479fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (off < 0) { 480fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGE("cannot seek mFd: %s (%d) %lld", strerror(errno), errno, (long long)mFd); 481fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang release(); 482fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 483fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang for (List<Track *>::iterator it = mTracks.begin(); 484fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang it != mTracks.end(); ++it) { 485fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang (*it)->resetInternal(); 486fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 48720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 489dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 490dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 491dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 492dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 493dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 494dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 495dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 496dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 497dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 498dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 499dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 500dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 501dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 502dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 503dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 504dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 505dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 506dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 50784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber int fd, const Vector<String16>& /* args */) const { 508dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 509dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 510dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 51125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang snprintf(buffer, SIZE, " %s track\n", getTrackType()); 512dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 513dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 514dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 515dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 516c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 51713210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 518377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); 51913210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 520dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 521dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 522dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 523dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 5248b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static 5258b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) { 5268b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (mime == NULL) { 5278b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 5288b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 5298b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strncasecmp(mime, "audio/", 6)) { 5308b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 5318b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "samr"; 5328b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 5338b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "sawb"; 5348b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 5358b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4a"; 5368b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 5378b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strncasecmp(mime, "video/", 6)) { 5388b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 5398b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4v"; 5408b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 5418b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "s263"; 5428b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 5438b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "avc1"; 5449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 5459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return "hvc1"; 5468b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 54725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (!strncasecmp(mime, "application/", 12)) { 54825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang return "mett"; 5498b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else { 55025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("Track (%s) other than video/audio/metadata is not supported", mime); 5518b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 5528b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 5538b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan} 5548b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan 555b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissenstatus_t MPEG4Writer::addSource(const sp<IMediaSource> &source) { 556bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 557bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 55829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Attempt to add source AFTER recording is started"); 559bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 560bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 561acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 562acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong CHECK(source.get() != NULL); 563acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 564acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong const char *mime; 565acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong source->getFormat()->findCString(kKeyMIMEType, &mime); 566acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 56725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (Track::getFourCCForMime(mime) == NULL) { 56825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("Unsupported mime '%s'", mime); 56925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang return ERROR_UNSUPPORTED; 57025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } 57125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang 57225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang // This is a metadata track or the first track of either audio or video 573acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // Go ahead to add the track. 574219f195159f93d627af2b243732e3f9020511a46James Dong Track *track = new Track(this, source, 1 + mTracks.size()); 57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 5762dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 5772dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 581acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.empty()) { 582acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("No source added"); 583acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return INVALID_OPERATION; 584acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 585acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 586a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 587a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 58893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 589a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 590a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 591a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 592a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 593a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 594a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 595a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 596a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 597a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 598a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 599a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 600a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 601a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 6027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() { 6037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // add device info and estimate space in 'moov' 6047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang char val[PROPERTY_VALUE_MAX]; 6057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size_t n; 6067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // meta size is estimated by adding up the following: 6077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - meta header structures, which occur only once (total 66 bytes) 6087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - size for each key, which consists of a fixed header (32 bytes), 6097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // plus key length and data length. 6107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 66; 6117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.version.release", val, NULL) 6127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 6137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Version, val, n + 1); 6147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32; 6157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 616da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang 617da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang if (property_get_bool("media.recorder.show_manufacturer_and_model", false)) { 618da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang if (property_get("ro.product.manufacturer", val, NULL) 619da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang && (n = strlen(val)) > 0) { 620da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang mMetaKeys->setString(kMetaKey_Manufacturer, val, n + 1); 621da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang mMoovExtraSize += sizeof(kMetaKey_Manufacturer) + n + 32; 622da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang } 623da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang if (property_get("ro.product.model", val, NULL) 624da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang && (n = strlen(val)) > 0) { 625da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang mMetaKeys->setString(kMetaKey_Model, val, n + 1); 626da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32; 627da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang } 6287c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 629da5c3beba9d9612aa0e80cc8ae668397438b4c49Hangyu Kuang#ifdef SHOW_MODEL_BUILD 6307c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.display.id", val, NULL) 6317c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 6327c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Build, val, n + 1); 6337c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32; 6347c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 6357c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif 6367c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang} 6377c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 6382dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 6392dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 6402dec2b5be2056c6d9428897dc672185872d30d17James Dong // 6412dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 6422dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 6432dec2b5be2056c6d9428897dc672185872d30d17James Dong 64478a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 6452dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 64678a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 6472dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 6482dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 6492dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 6502dec2b5be2056c6d9428897dc672185872d30d17James Dong 6512dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 6522dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 6532dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 65478a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 6552dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 6562dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 6572dec2b5be2056c6d9428897dc672185872d30d17James Dong 65878a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 659a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 66078a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 66178a1a286f736888ae7af8860b2c424af0d978848James Dong } 66278a1a286f736888ae7af8860b2c424af0d978848James Dong 66378a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 66478a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 66578a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 66678a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 6670ca31521644b9396829850f7400d23f9b107cc64Johan Redestig ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000; 66878a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 66978a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 67078a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 67178a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 67278a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 67378a1a286f736888ae7af8860b2c424af0d978848James Dong } 67478a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 67578a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 67678a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 67778a1a286f736888ae7af8860b2c424af0d978848James Dong } 6782dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6792dec2b5be2056c6d9428897dc672185872d30d17James Dong } 68078a1a286f736888ae7af8860b2c424af0d978848James Dong 6812dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 6822dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 6832dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6842dec2b5be2056c6d9428897dc672185872d30d17James Dong 6852dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 6862dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 6872dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 6882dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 6892dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6902dec2b5be2056c6d9428897dc672185872d30d17James Dong 6917c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // Account for the extra stuff (Geo, meta keys, etc.) 6927c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size += mMoovExtraSize; 6937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 694a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the" 695a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn " estimated moov size %" PRId64 " bytes", 6962dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 6972dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 6982dec2b5be2056c6d9428897dc672185872d30d17James Dong} 6992dec2b5be2056c6d9428897dc672185872d30d17James Dong 7002dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 701674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 70225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 704fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStartMeta = param; 70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 706a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 707a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 708a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 709a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 710a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 711a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 712a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 713a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 714a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 715a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 7162dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 7172dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 7182dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 7192dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 7202dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 7212dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7222dec2b5be2056c6d9428897dc672185872d30d17James Dong 7231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 7241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 7251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 7261f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 7271f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 7281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 7291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 7301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 7311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 732a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. " 733a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn "It is changed to %" PRId64 " bytes", 734d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 735d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 7361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 7371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 7381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 739b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 740b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 741b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 742b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 743b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 7442dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7452dec2b5be2056c6d9428897dc672185872d30d17James Dong 746de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui int32_t isRealTimeRecording; 747de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) { 748de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording = isRealTimeRecording; 749de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 750de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 751065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 75293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 753a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 754a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 755a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 75693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 757a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 758a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 759a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 760a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 7618f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 7628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 7638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 7648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 76543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 7663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("movie time scale: %d", mTimeScale); 7678f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 76877e8ae9967a078770416619e99ddb5b010def312James Dong /* 76977e8ae9967a078770416619e99ddb5b010def312James Dong * When the requested file size limit is small, the priority 77077e8ae9967a078770416619e99ddb5b010def312James Dong * is to meet the file size limit requirement, rather than 7717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to make the file streamable. mStreamableFile does not tell 7727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * whether the actual recorded file is streamable or not. 77377e8ae9967a078770416619e99ddb5b010def312James Dong */ 77477e8ae9967a078770416619e99ddb5b010def312James Dong mStreamableFile = 77577e8ae9967a078770416619e99ddb5b010def312James Dong (mMaxFileSizeLimitBytes != 0 && 77677e8ae9967a078770416619e99ddb5b010def312James Dong mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 77777e8ae9967a078770416619e99ddb5b010def312James Dong 7787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong /* 7797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory is true if the amount of data in moov box is 7807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * smaller than the reserved free space at the beginning of a file, AND 7817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * when the content of moov box is constructed. Note that video/audio 7827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * frame data is always written to the file but not in the memory. 7837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Before stop()/reset() is called, mWriteMoovBoxToMemory is always 7857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * false. When reset() is called at the end of a recording session, 7867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Moov box needs to be constructed. 7877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory 7897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to set to mStreamableFile so that if 7907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the file is intended to be streamable, it is set to true; 7917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * otherwise, it is set to false. When the value is set to false, 7927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * all the content of the moov box is written immediately to 7937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the end of the file. When the value is set to true, all the 7947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * content of the moov box is written to an in-memory cache, 7957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mMoovBoxBuffer, util the following condition happens. Note 7967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * that the size of the in-memory cache is the same as the 7977b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * reserved free space at the beginning of the file. 7987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7997b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 2) While the data of the moov box is written to an in-memory 8007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache, the data size is checked against the reserved space. 8017b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * If the data size surpasses the reserved space, subsequent moov 8027b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * data could no longer be hold in the in-memory cache. This also 8037b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * indicates that the reserved space was too small. At this point, 8047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * _all_ moov data must be written to the end of the file. 8057b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory must be set to false to direct the write 8067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to the file. 8077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 8087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 3) If the data size in moov box is smaller than the reserved 8097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space after moov box is completely constructed, the in-memory 8107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache copy of the moov box is written to the reserved free 8117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space. Thus, immediately after the moov is completedly 8127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * constructed, mWriteMoovBoxToMemory is always set to false. 8137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong */ 8147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 8157837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 8167837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 8177837c17063a4c50bc856ba59418516fdab731de7James Dong 818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8207837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8227837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 8232dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 8242dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 8252dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 8262dec2b5be2056c6d9428897dc672185872d30d17James Dong } 8272dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 8287837c17063a4c50bc856ba59418516fdab731de7James Dong } 82943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mEstimatedMoovBoxSize, 8); 83077e8ae9967a078770416619e99ddb5b010def312James Dong if (mStreamableFile) { 83177e8ae9967a078770416619e99ddb5b010def312James Dong // Reserve a 'free' box only for streamable file 83277e8ae9967a078770416619e99ddb5b010def312James Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 83377e8ae9967a078770416619e99ddb5b010def312James Dong writeInt32(mEstimatedMoovBoxSize); 83477e8ae9967a078770416619e99ddb5b010def312James Dong write("free", 4); 83577e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 83677e8ae9967a078770416619e99ddb5b010def312James Dong } else { 83777e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mOffset; 83877e8ae9967a078770416619e99ddb5b010def312James Dong } 8397837c17063a4c50bc856ba59418516fdab731de7James Dong 8407837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 841c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 8421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 8431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 8441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 8451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 8461acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 8471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 8491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 8501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 8511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 854a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 855a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 8571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 858a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 85925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 8631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 8641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 86637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 867674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 86837187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 869a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 870a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 87137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 872a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 873a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 87437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 87537187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 87637187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 87737187916a486504acaf83bea30147eb5fbf46ae5James Dong } 878a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 87937187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 880a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 881a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 8821c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 883b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping writer thread"); 884411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 885411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 886411ba422e3635d534928ffd81abf54f4f291c739James Dong } 8871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 8891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 8901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 8921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 8931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 8961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 897411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 898b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Writer thread stopped"); 8991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 9001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 90113f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 90213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 90313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 90413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 90513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 90613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 90713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 90813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 90913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 91013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 91113f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 91213f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 9133856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeCompositionMatrix"); 91413f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 91513f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 91613f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 91713f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 91813f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 91913f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 92013f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 92113f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 92213f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 92313f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 92413f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 92513f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 92613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 92713f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 92813f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 92913f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 93013f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 93113f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 93213f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 93313f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 93413f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 93513f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 93613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 93713f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 93813f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 93913f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 94013f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 94113f6284305e4b27395a23db7882d670bdb1bcae1James Dong 94213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 94313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 94413f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 94513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 94613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 94713f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 94813f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 94913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 95013f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 95113f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 95213f6284305e4b27395a23db7882d670bdb1bcae1James Dong 953411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 954411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 955411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 956411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 957411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 9584c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary free(mMoovBoxBuffer); 9594c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary mMoovBoxBuffer = NULL; 960411ba422e3635d534928ffd81abf54f4f291c739James Dong} 96113f6284305e4b27395a23db7882d670bdb1bcae1James Dong 962fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::finishCurrentSession() { 963fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang reset(false /* stopSource */); 964fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 965fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 966fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::switchFd() { 967fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGV("switchFd"); 968fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang Mutex::Autolock l(mLock); 969fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mSwitchPending) { 970fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return OK; 971fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 972fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 973fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mNextFd == -1) { 974fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGW("No FileDescripter for next recording"); 975fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return INVALID_OPERATION; 976fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 977fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 978fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSwitchPending = true; 979fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang sp<AMessage> msg = new AMessage(kWhatSwitch, mReflector); 980fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang status_t err = msg->post(); 981fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 982fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return err; 983fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 984fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 985fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::reset(bool stopSource) { 986674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 98737187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 988411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 989411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 990411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 991411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 992411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 993411ba422e3635d534928ffd81abf54f4f291c739James Dong } 994411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 995411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 996411ba422e3635d534928ffd81abf54f4f291c739James Dong } 99720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 99820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 99937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 10008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 100165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 100220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 100320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 1004fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang status_t status = (*it)->stop(stopSource); 100537187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 100637187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 100737187916a486504acaf83bea30147eb5fbf46ae5James Dong } 100820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 10108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 10118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 101220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 101365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 101465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 101565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 101665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 101765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 101865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 1019a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us", 102065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 10247837c17063a4c50bc856ba59418516fdab731de7James Dong 102537187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 102637187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 1027411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 102837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 102937187916a486504acaf83bea30147eb5fbf46ae5James Dong } 103037187916a486504acaf83bea30147eb5fbf46ae5James Dong 103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 10321acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 1033c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 10341f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); 1035c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 10361acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 1037c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 10381f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint64_t size = mOffset - mMdatOffset; 10391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 1040c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 10411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 1042c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 104320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Construct moov box now 10457837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 10467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = mStreamableFile; 10477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 10487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // There is no need to allocate in-memory cache 10497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // for moov box if the file is not streamable. 10507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 10517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 10527b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong CHECK(mMoovBoxBuffer != NULL); 10537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 1054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // mWriteMoovBoxToMemory could be set to false in 10577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // MPEG4Writer::write() method 10587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 10597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 10607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Content of the moov box is saved in the cache, and the in-memory 10617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // moov box needs to be written to the file in a single shot. 10627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 106343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 10647837c17063a4c50bc856ba59418516fdab731de7James Dong 10657837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 1066c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 10677837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 1068674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 10697837c17063a4c50bc856ba59418516fdab731de7James Dong 10707837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 1071c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 10727837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 10737837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 10747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } else { 10757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ALOGI("The mp4 file will not be streamable."); 10767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 10777837c17063a4c50bc856ba59418516fdab731de7James Dong 10787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Free in-memory cache for moov box 10797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mMoovBoxBuffer != NULL) { 10807837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 10817837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 10827837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 10837837c17063a4c50bc856ba59418516fdab731de7James Dong } 10847837c17063a4c50bc856ba59418516fdab731de7James Dong 10850c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 108620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1087411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 108837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 108920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 109020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1091efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() { 1092b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 1093efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 1094efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // while time function returns Unix epoch values which starts 1095efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // at 1970-01-01. Lets add the number of seconds between them 10962b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60); 10972b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen if (now < 0 || uint32_t(now) > UINT32_MAX - delta) { 10982b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen return 0; 10992b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen } 11002b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen uint32_t mpeg4Time = uint32_t(now) + delta; 1101efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson return mpeg4Time; 1102efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson} 1103efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson 1104efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 1105efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 1106b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 1107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 1108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 1109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 1110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 1111b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 1112b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 1113b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 1114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 1115b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 1116b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1117b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1118b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 1119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1120b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1123b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1124b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1125b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 1126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 1127b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1129b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 1130b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 1131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 113207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 113307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 113407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 1135e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeMetaBox(); 1136b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 1137b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 1138b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 1139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 1140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 1142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 11442cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 1145b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 1146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1147b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 1148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 1149b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 1150b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 11518284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 11528284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("isom"); 11538284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("3gp4"); 1154b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 11558284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 11568284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 1157b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 11588284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 1159b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1160b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 1162b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 116407ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 116507ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 116607ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 116707ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 116807ec01904613a0bac32caaa8444b4690998faed7James Dong 116907ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 117007ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 117196626b7f9a4e5c9e1e04f7f710383631d1470364Marco Nelissen if (property_get_bool("rw.media.record.test", false)) { 117207ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 117307ec01904613a0bac32caaa8444b4690998faed7James Dong } 117407ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 117507ec01904613a0bac32caaa8444b4690998faed7James Dong} 117607ec01904613a0bac32caaa8444b4690998faed7James Dong 117770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 117807ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 117907ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 118007ec01904613a0bac32caaa8444b4690998faed7James Dong return; 118107ec01904613a0bac32caaa8444b4690998faed7James Dong } 118207ec01904613a0bac32caaa8444b4690998faed7James Dong 118370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 118470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 118570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 118670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 118770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 118870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 118970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 119070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 119170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 119213aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 119313aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 119413aec890216948b0c364f8f92792129d0335f506James Dong return OK; 119513aec890216948b0c364f8f92792129d0335f506James Dong} 119613aec890216948b0c364f8f92792129d0335f506James Dong 119713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 119813aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 119913aec890216948b0c364f8f92792129d0335f506James Dong} 120013aec890216948b0c364f8f92792129d0335f506James Dong 120113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 120213aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 120313aec890216948b0c364f8f92792129d0335f506James Dong} 120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1205c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 1206c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1208c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1209c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1210c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 121803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 121903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 122003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 122103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 122203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 122303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 122403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 122503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 122603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 122703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 122803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 122903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 123003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 123180f78b773f92048944a850efb7b60629643370cdPraveen Chavanoff64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) { 123280f78b773f92048944a850efb7b60629643370cdPraveen Chavan off64_t old_offset = mOffset; 123380f78b773f92048944a850efb7b60629643370cdPraveen Chavan 123480f78b773f92048944a850efb7b60629643370cdPraveen Chavan const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs 123580f78b773f92048944a850efb7b60629643370cdPraveen Chavan 123680f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset(); 123780f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *currentNalStart = dataStart; 123880f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *nextNalStart; 123980f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *data = dataStart; 124080f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t nextNalSize; 124180f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ? 124280f78b773f92048944a850efb7b60629643370cdPraveen Chavan kExtensionNALSearchRange : buffer->range_length(); 124380f78b773f92048944a850efb7b60629643370cdPraveen Chavan 124480f78b773f92048944a850efb7b60629643370cdPraveen Chavan while (getNextNALUnit(&data, &searchSize, &nextNalStart, 124580f78b773f92048944a850efb7b60629643370cdPraveen Chavan &nextNalSize, true) == OK) { 124610cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */; 124780f78b773f92048944a850efb7b60629643370cdPraveen Chavan MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize); 124880f78b773f92048944a850efb7b60629643370cdPraveen Chavan addLengthPrefixedSample_l(nalBuf); 124980f78b773f92048944a850efb7b60629643370cdPraveen Chavan nalBuf->release(); 125080f78b773f92048944a850efb7b60629643370cdPraveen Chavan 125180f78b773f92048944a850efb7b60629643370cdPraveen Chavan currentNalStart = nextNalStart; 125280f78b773f92048944a850efb7b60629643370cdPraveen Chavan } 125380f78b773f92048944a850efb7b60629643370cdPraveen Chavan 125480f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t currentNalOffset = currentNalStart - dataStart; 125580f78b773f92048944a850efb7b60629643370cdPraveen Chavan buffer->set_range(buffer->range_offset() + currentNalOffset, 125680f78b773f92048944a850efb7b60629643370cdPraveen Chavan buffer->range_length() - currentNalOffset); 125780f78b773f92048944a850efb7b60629643370cdPraveen Chavan addLengthPrefixedSample_l(buffer); 125880f78b773f92048944a850efb7b60629643370cdPraveen Chavan 125980f78b773f92048944a850efb7b60629643370cdPraveen Chavan return old_offset; 126080f78b773f92048944a850efb7b60629643370cdPraveen Chavan} 126180f78b773f92048944a850efb7b60629643370cdPraveen Chavan 1262c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 1263c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 126430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 126530ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 126603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1267b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 1268b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 1269c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1270b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 1271c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1272b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 1273c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1274b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1275c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1276c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 1277c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1278c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1279c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 1280b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1281b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 1282b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 128343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(length, 65536); 128430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1285b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 1286c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1287b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1288c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1289c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1290b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 1291b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 129230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 129330ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 129430ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 129530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 12967837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 1297674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 12987837c17063a4c50bc856ba59418516fdab731de7James Dong 12997837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 13007837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 13017b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 1302c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 13031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 13047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // The reserved moov box at the beginning of the file 13057b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // is not big enough. Moov box should be written to 13067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the end of the file from now on, but not to the 13077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // in-memory cache. 13087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 13097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // We write partial moov box that is in the memory to 13107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the file first. 1311c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 13127837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 13137837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 13147837c17063a4c50bc856ba59418516fdab731de7James Dong } 1315674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 1316674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 13177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ::write(mFd, ptr, bytes); 13187837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 13197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 13207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // All subsequent moov box content will be written 13217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // to the end of the file. 13227837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 13237837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 13247837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 13257837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 13267837c17063a4c50bc856ba59418516fdab731de7James Dong } 13277837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1328674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 13297837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 13307837c17063a4c50bc856ba59418516fdab731de7James Dong } 13317837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 13327837c17063a4c50bc856ba59418516fdab731de7James Dong} 13337837c17063a4c50bc856ba59418516fdab731de7James Dong 1334e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) { 1335e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mBoxes.push_back(mWriteMoovBoxToMemory? 1336e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mMoovBoxBufferOffset: mOffset); 1337e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 1338e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 1339e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(id); 1340e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1341e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 13430c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13457837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 13467837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 13530c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1355c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13587837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 13597837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 13607837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 13617837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1362c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 13637837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 13647837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1365c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 13667837c17063a4c50bc856ba59418516fdab731de7James Dong } 136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1370674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1375674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 137820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1380674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 138120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 138420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1385674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 138620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 138720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1390674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 139120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 13940c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 1395674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 139720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 139807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 139907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 140007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 140107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 140207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 140307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 140407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 140507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 140607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 140707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 140807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 140907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 141007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 141107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 141207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 141307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 141407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 141507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 141607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 141707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 141807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 141907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 142007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 142107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 142207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 142307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 142407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 142507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 142607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 142707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 142807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 142907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 143007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 143107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 143207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 143307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 143407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 143507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 143607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 143707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 143807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 143907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 144007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 144107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 144207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 144307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 144407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 144507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 144607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 144707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 144807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 144907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 145007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 145107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 145207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 145307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 145407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 145507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 145607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 145707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 145807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 145907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 146007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 146107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 146207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 146307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 146407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 146507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 14667c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 30; 146707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 146807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 146907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 1470e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) { 1471e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (captureFps <= 0.0f) { 1472e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return BAD_VALUE; 1473e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 1474e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 14757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps); 14767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32; 14777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 1478e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return OK; 1479e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1480e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 14814dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) { 14824dbff11975e737482537e1636051690188f3fbc4Praveen Chavan if (layerCount > 9) { 14834dbff11975e737482537e1636051690188f3fbc4Praveen Chavan return BAD_VALUE; 14844dbff11975e737482537e1636051690188f3fbc4Praveen Chavan } 14854dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 14864dbff11975e737482537e1636051690188f3fbc4Praveen Chavan if (layerCount > 0) { 14874dbff11975e737482537e1636051690188f3fbc4Praveen Chavan mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount); 14884dbff11975e737482537e1636051690188f3fbc4Praveen Chavan mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32; 14894dbff11975e737482537e1636051690188f3fbc4Praveen Chavan } 14904dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 14914dbff11975e737482537e1636051690188f3fbc4Praveen Chavan return OK; 14924dbff11975e737482537e1636051690188f3fbc4Praveen Chavan} 14934dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 1494fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::notifyApproachingLimit() { 1495fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang Mutex::Autolock autolock(mLock); 1496fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // Only notify once. 1497fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mSendNotify) { 1498fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return; 1499fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1500fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGW("Recorded file size is approaching limit %" PRId64 "bytes", 1501fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMaxFileSizeLimitBytes); 1502fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING, 0); 1503fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSendNotify = true; 1504fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1505fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 150620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1507674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 150920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 151078a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 151178a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 151278a1a286f736888ae7af8860b2c424af0d978848James Dong} 151378a1a286f736888ae7af8860b2c424af0d978848James Dong 1514d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1515d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1516d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1517d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1518d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1519956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1520d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1521d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1522d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1523d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 15241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 152577e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 152677e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 152777e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 152877e8ae9967a078770416619e99ddb5b010def312James Dong } 1529fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1530acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1531acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1532acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1533acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1534d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1535d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1536fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangbool MPEG4Writer::approachingFileSizeLimit() { 1537fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // No limit 1538fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mMaxFileSizeLimitBytes == 0) { 1539fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return false; 1540fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1541fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1542fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1543fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang for (List<Track *>::iterator it = mTracks.begin(); 1544fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang it != mTracks.end(); ++it) { 1545fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1546fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1547fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1548fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (!mStreamableFile) { 1549fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // Add 1024 bytes as error tolerance 1550fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return nTotalBytesEstimate + 1024 >= (90 * mMaxFileSizeLimitBytes) / 100; 1551fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1552fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1553fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return (nTotalBytesEstimate >= (90 * mMaxFileSizeLimitBytes) / 100); 1554fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1555fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1556d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1557d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1558d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1559d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1560d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1561d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1562d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1563d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1564d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1565d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1566d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1567d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1568d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1569d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1570d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 157125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 157225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 157325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 157425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 157525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 157625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 157725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 157825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 157925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 158025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 158125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 158225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 158325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1584f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1585a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("setStartTimestampUs: %" PRId64, timeUs); 158643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 15873c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1588065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1589f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1590a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs); 15913c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 15923c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 15933c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1594f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 15953c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 15963c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 15973c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 15983c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 159958ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 160058ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 160158ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 160258ae9c530247668f8af36e30d228c716c226b3d4James Dong} 160358ae9c530247668f8af36e30d228c716c226b3d4James Dong 160420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 160520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 160620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1607b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId) 160820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 160925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 161020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 161120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1612a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1613a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1614eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1615fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mGotStartKeyFrame(false), 16169db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed(false), 1617bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1618c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1619956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1620be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1621c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1622c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1623c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)), 1624c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)), 1625c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1626c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)), 1627c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)), 162820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 162925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1630548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 163113f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 163213f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 163319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 16348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 16351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 16361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 16371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 16389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC); 16391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 164025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mIsVideo = !strncasecmp(mime, "video/", 6); 16411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 16421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 16431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1644b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar // store temporal layer count 164525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo) { 1646b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar int32_t count; 1647b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) { 1648b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar mOwner->setTemporalLayerCount(count); 1649b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar } 1650b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar } 1651b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar 1652c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1653c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1654c059860c73678a202bfa33062723e8f82fb779d9James Dong 1655fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang// Clear all the internal states except the CSD data. 1656fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::Track::resetInternal() { 1657fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mDone = false; 1658fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mPaused = false; 1659fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mResumed = false; 1660fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStarted = false; 1661fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mGotStartKeyFrame = false; 1662fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mIsMalformed = false; 1663fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mTrackDurationUs = 0; 1664fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mEstimatedTrackSizeBytes = 0; 1665fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSamplesHaveSameSize = 0; 1666fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mStszTableEntries != NULL) { 1667fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mStszTableEntries; 1668fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000); 1669fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1670fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1671fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mStcoTableEntries != NULL) { 1672fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mStcoTableEntries; 1673fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000); 1674fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1675fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mCo64TableEntries != NULL) { 1676fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mCo64TableEntries; 1677fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000); 1678fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1679fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1680fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mStscTableEntries != NULL) { 1681fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mStscTableEntries; 1682fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000); 1683fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1684fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mStssTableEntries != NULL) { 1685fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mStssTableEntries; 1686fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000); 1687fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1688fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mSttsTableEntries != NULL) { 1689fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mSttsTableEntries; 1690fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000); 1691fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1692fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mCttsTableEntries != NULL) { 1693fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mCttsTableEntries; 1694fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000); 1695fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1696fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mReachedEOS = false; 1697fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1698fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 16991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 17001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1701c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1702c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 1703c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 1704c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1705c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 17061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 170778a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 170878a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 170978a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 171078a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1711c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1712c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1713c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1714c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 171578a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 171678a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 171778a1a286f736888ae7af8860b2c424af0d978848James Dong } 17181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 17191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 17201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 17211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 17221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1723c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(chunkId)); 1724c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(sampleId)); 1725c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(1)); 17261f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 17271f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 17281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1729c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 17301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 17311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 17321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 173379761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 17341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 17355a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 1736377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGW("0-duration samples found: %zu", sampleCount); 17375a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1738c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1739c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 17401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 17411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1742965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1743965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1744965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 174525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (!mIsVideo) { 1746965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1747965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1748c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1749c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1750965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1751965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1752fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::setNextFd(int fd) { 1753fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGV("addNextFd"); 1754fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang Mutex::Autolock l(mLock); 1755fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mLooper == NULL) { 1756fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mReflector = new AHandlerReflector<MPEG4Writer>(this); 1757fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLooper = new ALooper; 1758fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLooper->registerHandler(mReflector); 1759fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLooper->start(); 1760fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1761fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1762fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mNextFd != -1) { 1763fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // No need to set a new FD yet. 1764fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return INVALID_OPERATION; 1765fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1766fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mNextFd = fd; 1767fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return OK; 1768fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1769fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1770c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1771c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1772c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1773c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1774c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1775c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1776c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 17771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 17781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1779c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 17803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 1781c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1782c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1783c059860c73678a202bfa33062723e8f82fb779d9James Dong 1784c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1785c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1786c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1787c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1788c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1789c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1790c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1791c059860c73678a202bfa33062723e8f82fb779d9James Dong 1792c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1793c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1794c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1795c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1796c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1797c059860c73678a202bfa33062723e8f82fb779d9James Dong 179843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 179919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 180019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 1801fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::onMessageReceived(const sp<AMessage> &msg) { 1802fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang switch (msg->what()) { 1803fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang case kWhatSwitch: 1804fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang { 1805fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang finishCurrentSession(); 1806fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLock.lock(); 1807fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang int fd = mNextFd; 1808fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mNextFd = -1; 1809fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLock.unlock(); 1810fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang initInternal(fd); 1811fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang start(mStartMeta.get()); 1812fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSwitchPending = false; 1813fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED, 0); 1814fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang break; 1815fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1816fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang default: 1817fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang TRESPASS(); 1818fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1819fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1820fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 182119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 182219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 1823fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 182419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 182519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 18269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim uint32_t type; 18279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const void *data = NULL; 18289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t size = 0; 182919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 18309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mMeta->findData(kKeyAVCC, &type, &data, &size); 18319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) { 18329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mMeta->findData(kKeyHVCC, &type, &data, &size); 183319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 183419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 183519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 183619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 18379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (esds.getCodecSpecificInfo(&data, &size) != OK) { 18389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim data = NULL; 18399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size = 0; 184019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 184119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 184219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 18439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) { 18449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mGotAllCodecSpecificData = true; 18459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 184620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 184720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 184820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 184920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1851c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 1852c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 1853c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 1854c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 1855c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 1856c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 1857c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 1858c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 1859c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 1860c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 1861c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 1862c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 1863c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 1864c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 1865c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 1866c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 186720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 186820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 186920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 187020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 187120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 187220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 187393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 18743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 187593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 187693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 187793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 187893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 187993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 188093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 1881a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs); 188293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 188393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 188493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 188593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 188693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 188793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 18881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 18891c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 18903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 18911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 18921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 18931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 18941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 18951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18961c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 18973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 18981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 18991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 19001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 19021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 19031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 19051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 19061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 19071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 19081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 191143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 19121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 19131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1914fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1915a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("writeChunkToFile: %" PRId64 " from %s track", 191625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang chunk->mTimeStampUs, chunk->mTrack->getTrackType()); 1917fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1918fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1919fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1920fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1921fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 19229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc()) 192380f78b773f92048944a850efb7b60629643370cdPraveen Chavan ? addMultipleLengthPrefixedSamples_l(*it) 1924fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1925fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1926fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1927fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1928fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 19291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 19321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1933fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 19341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1935fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 19361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 19371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1938fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 19393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 19401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 194170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 194270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1943e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 194470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 19451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 194670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 194770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 194870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 19491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 1950377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGD("%zu chunks are written in the last batch", outstandingChunks); 19511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 19521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1953fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 19543856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 19551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 19571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 19581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 19591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 19601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 19611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 19621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 19631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 19641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 19651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 19703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 1971fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 19721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 19751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 19761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1977fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 19781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 19791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 19801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1981fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1982fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1983fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 198470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 198570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 198670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 198770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 198870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 198970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 199070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1991fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 19921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1994fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1995fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 19961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 19971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19981c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 19993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 20001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 2001a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 2002fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 2003fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 20041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 2005fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 2006fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 2007fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 2008fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 20091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 20101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 20111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 2012de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // In real time recording mode, write without holding the lock in order 2013de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // to reduce the blocking time for media track threads. 2014de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // Otherwise, hold the lock until the existing chunks get written to the 2015de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // file. 2016fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 2017de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 2018de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.unlock(); 2019de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2020fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 2021de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 2022de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.lock(); 2023de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2024fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 20251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 2026fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 2027fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 20281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 20291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 20301c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 20313856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 20321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 20331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 20341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 2035e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 20361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 20371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 20381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 20391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 204070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 204170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 20421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 20431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 20441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 20451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 20461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 20471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 20481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 20491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 2050411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 20511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 20521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 20531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 20541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 205593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 2056a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 2057a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 2058a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 2059a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 2060a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 206125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 206293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 206319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 206419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 206519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 206670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 206719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 206813f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 206925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 207013f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 207113f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 207213f6284305e4b27395a23db7882d670bdb1bcae1James Dong 207393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 207493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2075f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 2076de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 2077a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 2078a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 2079a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 2080a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 2081a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 2082a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 208386b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 208486b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 2085a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 208686b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 208786b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 208886b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 208986b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 209086b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 2091a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs); 2092a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2093a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2094f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 2095a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2096f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 209725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 209825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 209925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 210025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 210120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 210220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 210320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 210420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 210520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 210620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 2107eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 2108c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 210925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 2110956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 21111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 211243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 2113826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar mLastDecodingTimeUs = -1; 211420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 211525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 211620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 211725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 211825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 211920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 212020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 212137187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 2122a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 212337187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 2124a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 2125a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2126fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::Track::stop(bool stopSource) { 2127fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("%s track stopping. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop"); 2128eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 212929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 2130eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 2131eaae38445a340c4857c1c5569475879a728e63b7James Dong } 2132eaae38445a340c4857c1c5569475879a728e63b7James Dong 213320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 213437187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 213520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 213620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 2137fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (stopSource) { 2138fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("%s track source stopping", getTrackType()); 2139fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSource->stop(); 2140fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("%s track source stopped", getTrackType()); 2141fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 214272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 214320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 214420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 2145377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 214637187916a486504acaf83bea30147eb5fbf46ae5James Dong 2147fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("%s track stopped. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop"); 214837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 214920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 215020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 215125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 215225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 215325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 215425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 215520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 215620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 215720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 215820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 215937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 2160377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT return (void *)(uintptr_t)err; 216120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 216220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 21643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 21653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 21673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 21683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 21693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 21713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 21723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 21743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 21753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 21763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 217747d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar const uint8_t *nextStartCode = findNextNalStartCode(data, length); 21783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 21793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 218029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 21813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 21823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 21853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 21863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 218729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 21883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 21893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 21913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 21923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 21933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 21943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 21953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 21963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 21973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 219807b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar // COULD DO: set profile/level to the lowest required to support all SPSs 219929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 22003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 22013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 22043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 22053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 22063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 22083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 22093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 22113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 22123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 22133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 22153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 22169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyCodecSpecificData(data, size, 4 + 7); 22179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 22189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData( 22209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size) { 22219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGV("copyHEVCCodecSpecificData"); 22229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2) 22249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyCodecSpecificData(data, size, 23); 22259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 22269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData( 22289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, size_t minLength) { 22299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (size < minLength) { 2230377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 22313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 22359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 22369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 22379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 22389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = size; 22403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 22413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 22423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 22433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 22453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 22463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22473856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 22483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 22493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 22503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 22513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 22523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 22533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 22543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 22553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 22563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 22573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 22583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 22593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 22603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 22613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 22623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 226329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 22643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 22673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 22683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 22703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 22713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 227229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 22733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 22763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 22773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 22793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 228029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 22813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 22853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 22893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 22903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 22913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 22923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 22953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 22963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 22973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 229829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 22993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 23003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 23023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 2303377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 23043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 23053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 23083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 23093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 23103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 23113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 231229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 23133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 23143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 2316377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 23173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 23183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23201374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 23211374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 23221374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 23231374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 23243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 23253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 23263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 23273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 23283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 232929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 23303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 23313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23331374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 23343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 23353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 2336548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 233703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 233803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 2339548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 234003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 234129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 234203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 234303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 234403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 2346377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 234703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 234803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 234903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 23513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 23523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 235303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 235403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 235603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 235703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 235803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 23603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 236103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 23629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 23639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = 0; 23649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 23659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 23669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 236703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 23683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 23693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 23703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 23713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 237203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2374b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2375b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 2376b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2377b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 2378b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 237903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 23813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 23823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 23833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 23843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 23853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 23863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 23873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 23883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 23893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 23903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 23913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 23923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 23933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 23943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 23963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 23973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 23983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 23993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 24003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 24013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 24023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 24033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 24043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 24053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 24063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 24073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 24083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 24093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 24103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 241103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 241203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 241303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 241403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 24159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData( 24179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, HevcParameterSets ¶mSets) { 24189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGV("parseHEVCCodecSpecificData"); 24209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *tmp = data; 24219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *nextStartCode = data; 24229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t bytesLeft = size; 24239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 242447d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4); 24259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4); 24269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (err != OK) { 24279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 24289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Move on to find the next parameter set 24319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bytesLeft -= nextStartCode - tmp; 24329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim tmp = nextStartCode; 24339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t csdSize = 23; 24369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const size_t numNalUnits = paramSets.getNumNalUnits(); 24379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) { 24389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim int type = kMandatoryHevcNalUnitTypes[i]; 24399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 24409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (numParamSets == 0) { 24419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Cound not find NAL unit of type %d", type); 24429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 24439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) { 24469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim int type = kHevcNalUnitTypes[i]; 24479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 24489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (numParamSets > 0xffff) { 24499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Too many seq parameter sets (%zu) found", numParamSets); 24509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 24519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim csdSize += 3; 24539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t j = 0; j < numNalUnits; ++j) { 24549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (paramSets.getType(j) != type) { 24559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim continue; 24569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim csdSize += 2 + paramSets.getSize(j); 24589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = csdSize; 24619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return OK; 24629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 24639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData( 24659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size) { 24669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData != NULL) { 24689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Already have codec specific data"); 24699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 24709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (size < 4) { 24739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Codec specific data length too short: %zu", size); 24749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 24759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Data is in the form of HEVCCodecSpecificData 24789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (memcmp("\x00\x00\x00\x01", data, 4)) { 24799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyHEVCCodecSpecificData(data, size); 24809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim HevcParameterSets paramSets; 24839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) { 24843d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim ALOGE("failed parsing codec specific data"); 24859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 24869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificData = malloc(mCodecSpecificDataSize); 24899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 24909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = 0; 24919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 24929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 24939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData, 24953d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2); 24969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (err != OK) { 24973d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim ALOGE("failed constructing HVCC atom"); 24989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return err; 24999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 25009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 25019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return OK; 25029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 25039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 2504872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 2505872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 2506872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 2507872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 2508872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 2509872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2510872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 2511872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 2512872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2513872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 2514872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2515872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2516872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2517872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 2518872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2519872a481558350634a3fd5cb67939de288af00ecbJames Dong} 2520872a481558350634a3fd5cb67939de288af00ecbJames Dong 252162a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuangvoid MPEG4Writer::Track::dumpTimeStamps() { 252262a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang ALOGE("Dumping %s track's last 10 frames timestamp ", getTrackType()); 252362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang std::string timeStampString; 252462a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang for (std::list<std::pair<int64_t, int64_t>>::iterator num = mTimestampDebugHelper.begin(); 252562a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang num != mTimestampDebugHelper.end(); ++num) { 252662a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang timeStampString += "(" + std::to_string(num->first)+ 252762a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang "us, " + std::to_string(num->second) + "us) "; 252862a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang } 252962a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang ALOGE("%s", timeStampString.c_str()); 253062a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang} 253162a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang 253237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 253330ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 253413aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 253543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 253613aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 253713aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 25387c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar int32_t nActualFrames = 0; // frames containing non-CSD data (non-0 length) 253913aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 2540965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 2541965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 2542965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 2543965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 2544965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 2545000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 2546a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 2547965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 2548000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 2549000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2550000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 255143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2552c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 2553e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2554a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 2555a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 255625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (mIsVideo) { 2557a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 255825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else { 255925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0); 2560a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 2561de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2562de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2563de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2564de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2565985f838934510983d8a887461e98dca60a6e858fJames Dong 2566d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 256720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 256893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 256920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 257025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *trackName = getTrackType(); 257193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 257220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 257320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 257420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 257513aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 257620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 257720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 257820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2579a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 2580a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 2581a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2582a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2583a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2584a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2585a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2586a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2587a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 258830ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 258930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 259003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 259103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 259203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 25937c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // if config format (at track addition) already had CSD, keep that 25947c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // UNLESS we have not received any frames yet. 25957c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // TODO: for now the entire CSD has to come in one frame for encoders, even though 25967c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // they need to be spread out for decoders. 25977c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar if (mGotAllCodecSpecificData && nActualFrames > 0) { 25987c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar ALOGI("ignoring additional CSD for video track after first frame"); 25997c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else { 26007c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar mMeta = mSource->getFormat(); // get output format after format change 26016e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang status_t err; 26027c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar if (mIsAvc) { 26036e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang err = makeAVCCodecSpecificData( 26047c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar (const uint8_t *)buffer->data() 26057c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar + buffer->range_offset(), 26067c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 26077c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else if (mIsHevc) { 26086e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang err = makeHEVCCodecSpecificData( 26097c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar (const uint8_t *)buffer->data() 26107c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar + buffer->range_offset(), 26117c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 26127c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else if (mIsMPEG4) { 26137c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(), 26147c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 26157c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } 261630ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 261730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 261830ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 261930ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 26206e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang if (OK != err) { 26216e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang mSource->stop(); 26226e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 26236e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang mTrackId | MEDIA_RECORDER_TRACK_ERROR_GENERAL, err); 26246e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang break; 26256e80328a71d93af64c2e2618cf1b5005f5dfdb76Hangyu Kuang } 262630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2627548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 262830ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2629a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2630a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2631e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang // Per-frame metadata sample's size must be smaller than max allowed. 2632e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang if (!mIsVideo && !mIsAudio && buffer->range_length() >= kMaxMetadataSize) { 2633e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang ALOGW("Buffer size is %zu. Maximum metadata buffer size is %lld for %s track", 2634e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang buffer->range_length(), (long long)kMaxMetadataSize, trackName); 2635e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang buffer->release(); 2636e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang mSource->stop(); 2637e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang mIsMalformed = true; 2638e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang break; 2639e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang } 2640e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang 26417c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar ++nActualFrames; 26427c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar 2643d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2644d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2645d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2646d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2647d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2648d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2649d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2650d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2651d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2652d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 26539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mIsAvc || mIsHevc) StripStartcode(copy); 2654e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2655b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 26569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mIsAvc || mIsHevc) { 2657b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2658b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2659b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2660b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2661b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2662b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2663050b28a593350047845a45a14cc5026221ac1620James Dong 2664d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 26651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 26661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 26671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2668d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2669fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mOwner->switchFd() != OK) { 2670fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGW("Recorded file size exceeds limit %" PRId64 "bytes", 2671fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mOwner->mMaxFileSizeLimitBytes); 2672fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSource->stop(); 2673fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mOwner->notify( 2674fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2675fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } else { 2676fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGV("%s Current recorded file size exceeds limit %" PRId64 "bytes. Switching output", 2677fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang getTrackType(), mOwner->mMaxFileSizeLimitBytes); 2678fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2679d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang copy->release(); 2680d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2681d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2682fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 2683d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2684316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds", 2685316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang mOwner->mMaxFileDurationLimitUs); 2686d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2687d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang copy->release(); 2688d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 2689d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2690d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2691d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2692fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mOwner->approachingFileSizeLimit()) { 2693fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mOwner->notifyApproachingLimit(); 2694fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2695050b28a593350047845a45a14cc5026221ac1620James Dong 2696d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2697d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2698d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2699d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2700fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // For video, skip the first several non-key frames until getting the first key frame. 2701fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mIsVideo && !mGotStartKeyFrame && !isSync) { 2702fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("Video skip non-key frame"); 2703fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang copy->release(); 2704fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang continue; 2705fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2706fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mIsVideo && isSync) { 2707fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mGotStartKeyFrame = true; 2708fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2709d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2710c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 271170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2712f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2713f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 27148428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 27153c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 271648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2717a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 27188428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 271911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) { 272011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2721d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 27229db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 27239db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 272411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 272511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 27268428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 272711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) { 272811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2729d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 27309db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 27319db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 273211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 273311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 27348428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2735a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2736a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 273762a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang std::pair<int64_t, int64_t> timestampPair; 2738a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 273962a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang timestampPair.first = timestampUs; 274011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 274111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2742d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 27439db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 27449db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 274511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 274611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 274725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo) { 2748965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2749965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2750965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2751000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 2752965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 2753965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 2754965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2755965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 2756826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar 2757826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar // ensure non-negative, monotonic decoding time 2758826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar if (mLastDecodingTimeUs < 0) { 2759826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar decodingTimeUs = std::max((int64_t)0, decodingTimeUs); 2760826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar } else { 276138f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang // increase decoding time by at least the larger vaule of 1 tick and 276238f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang // 0.1 milliseconds. This needs to take into account the possible 276338f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang // delta adjustment in DurationTicks in below. 276438f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang decodingTimeUs = std::max(mLastDecodingTimeUs + 276538f4cbed37d5788e488fd39ccab0c78b07e89207Hangyu Kuang std::max(100, divUp(1000000, mTimeScale)), decodingTimeUs); 2766826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar } 2767826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar 2768826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar mLastDecodingTimeUs = decodingTimeUs; 2769000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 2770000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 277111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) { 277211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2773d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 27749db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 27759db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 277611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 277711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2778965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 2779a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64, 2780000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 2781000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2782000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 2783000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 2784000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 278511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) { 278611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2787d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 27889db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 27899db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 279011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 279111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2792c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 279343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 279443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 279543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 279643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 279743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 279843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 279943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 280043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 280143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 280243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 280343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 280443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 280543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 280643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 280743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 2808000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2809000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 2810c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 2811000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2812000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2813000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 2814000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2815000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2816000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2817000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2818000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2819000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2820000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2821965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2822872a481558350634a3fd5cb67939de288af00ecbJames Dong 2823de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2824872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2825872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 2826e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2827e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2828872a481558350634a3fd5cb67939de288af00ecbJames Dong 282911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 283011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2831d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 28329db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 28339db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 283411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 283511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2836a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64, 283711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, previousPausedDurationUs); 2838c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2839c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 28403b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 28413b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 28425a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 28435a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 28445a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 28455a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 28465a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 28475a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 28485a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 28495a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2850c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 2851f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track", 2852f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang (long long)timestampUs, (long long)lastTimestampUs, trackName); 285311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 28540332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang mSource->stop(); 28559db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 28569db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 28578c460498c028888c533ab442be12b6d4b669b965James Dong } 28588c460498c028888c533ab442be12b6d4b669b965James Dong 285985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // if the duration is different for this sample, see if it is close enough to the previous 286085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // duration that we can fudge it and use the same value, to avoid filling the stts table 286185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // with lots of near-identical entries. 286285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // "close enough" here means that the current duration needs to be adjusted by less 286385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // than 0.1 milliseconds 286485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { 286585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL 286685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen + (mTimeScale / 2)) / mTimeScale; 286785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (deltaUs > -100 && deltaUs < 100) { 286885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // use previous ticks, and adjust timestamp as if it was actually that number 286985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // of ticks 287085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen currDurationTicks = lastDurationTicks; 287185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen timestampUs += deltaUs; 287285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 287385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 2874c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 2875c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 2876c059860c73678a202bfa33062723e8f82fb779d9James Dong 2877a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2878a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2879c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 288079761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2881be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2882be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2883be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2884be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2885965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2886be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2887be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2888c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2889be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2890be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 28918644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2892be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2893a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64, 289411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, lastTimestampUs); 28958644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2896c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 28978644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 289862a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang timestampPair.second = timestampUs; 289962a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang // Insert the timestamp into the mTimestampDebugHelper 290062a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang if (mTimestampDebugHelper.size() >= kTimestampDebugCount) { 290162a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang mTimestampDebugHelper.pop_front(); 290262a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang } 290362a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang mTimestampDebugHelper.push_back(timestampPair); 290420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2905d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 2906c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 2907d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2908d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 290993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 291093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 291193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 291293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2913faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 291493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 291543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 291680f78b773f92048944a850efb7b60629643370cdPraveen Chavan off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy) 291758ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 2918c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2919c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count = (mOwner->use32BitFileOffset() 2920c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 2921c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 2922c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2923c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (count == 0) { 29241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 292558ae9c530247668f8af36e30d228c716c226b3d4James Dong } 292658ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 292758ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 292858ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 292958ae9c530247668f8af36e30d228c716c226b3d4James Dong } 293013aec890216948b0c364f8f92792129d0335f506James Dong 293113aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 293213aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 29331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 29341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 293513aec890216948b0c364f8f92792129d0335f506James Dong } else { 293613aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 293713aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 293813aec890216948b0c364f8f92792129d0335f506James Dong } else { 293943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 294043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 294143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 294243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 294343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 294413aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 294513aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 2946c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 2947c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 2948c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 294913aec890216948b0c364f8f92792129d0335f506James Dong } 29501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 295113aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 295213aec890216948b0c364f8f92792129d0335f506James Dong } 295313aec890216948b0c364f8f92792129d0335f506James Dong } 295413aec890216948b0c364f8f92792129d0335f506James Dong } 295513aec890216948b0c364f8f92792129d0335f506James Dong 295620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 295725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 295845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 295962a94906c545fd9d88fb9d8ff6553bc903f73056Hangyu Kuang dumpTimeStamps(); 2960690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2961f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 296245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2963bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2964be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 296513aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 296643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2967c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(1, mStszTableEntries->count()); 296858ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 29691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 29701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 297113aec890216948b0c364f8f92792129d0335f506James Dong } 297213aec890216948b0c364f8f92792129d0335f506James Dong 2973be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2974be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2975be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2976c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 1) { 29778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 297879761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2979be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2980be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2981be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2982a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2983c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() <= 2) { 298479761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2985a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 298679761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2987a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2988a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 298979761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2990a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2991a472613aec322e25891abf5c77bf3f7e3c244920James Dong 299243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // The last ctts box may not have been written yet, and this 299343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // is to make sure that we write out the last ctts box. 299443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 299543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (cttsSampleCount > 0) { 299643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 299743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 299843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 299943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 3000c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 300125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 300243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 300343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 300443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 3005df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 300611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih count, nZeroLengthFrames, mStszTableEntries->count(), trackName); 3007872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 3008a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs()); 3009872a481558350634a3fd5cb67939de288af00ecbJames Dong } 3010365a963142093a1cd8efdcea76b5f65096a5b115James Dong 301137187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 301237187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 301337187916a486504acaf83bea30147eb5fbf46ae5James Dong } 301437187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 3015365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 3016365a963142093a1cd8efdcea76b5f65096a5b115James Dong 301745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 30189db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang if (mIsMalformed) { 30199db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang return true; 30209db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang } 30219db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang 3022c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { // no samples written 302329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 302445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 302545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 302645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 302725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo && mStssTableEntries->count() == 0) { // no sync frames for video 302829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 302945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 303045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 303145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 303245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 303345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 303445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 303545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 303645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 303745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 303845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 303943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 304007ec01904613a0bac32caaa8444b4690998faed7James Dong 304107ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 304207ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 304307ec01904613a0bac32caaa8444b4690998faed7James Dong return; 304407ec01904613a0bac32caaa8444b4690998faed7James Dong } 304507ec01904613a0bac32caaa8444b4690998faed7James Dong 304643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 304743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 304843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 304943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 305025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mIsAudio ? 0: 1); 305143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 305243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 305343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 305443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 305543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 305643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 305743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 3058c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 305943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 306086b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 306186b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 306286b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 306386b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 306486b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 306586b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 306686b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 306786b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 306886b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 306986b7f47aa7482424cf8fd248f1315311919be3b0James Dong 307086b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 307170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 307270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 307386b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 307470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 307507ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 307607ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 307707ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 307807ec01904613a0bac32caaa8444b4690998faed7James Dong 307943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 308043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 308143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 308243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 308370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 308470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 308570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 308670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 308770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 308870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 308970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 309070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 309143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 309243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 309343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 3094faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 3095a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("trackProgressStatus: %" PRId64 " us", timeUs); 3096c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 3097215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 3098215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 3099a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs); 3100bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 310193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 310293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 310393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 310493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 3105faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 3106bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 3107faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 3108bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 3109faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 3110faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 3111faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 3112faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 3113bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 3114bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 3115faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 3116faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 3117faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 3118faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 3119faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 3120faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 3121bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3122bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 3123faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 3124faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 3125faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 3126bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3127bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 3128faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 3129faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 3130faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 3131faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 3132d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 3133a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs); 3134e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 3135d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 3136e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 3137e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 3138e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 3139a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs); 3140e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 3141e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 3142e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 3143e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 3144de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const { 3145de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui return mIsRealTimeRecording; 3146de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui} 3147de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 3148b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 3149b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 3150b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 3151b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 31521c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 31533856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 31541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 31551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 31561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 315713aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 315820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 315920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31603b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 3161c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 316220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 316320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3164d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 3165d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 3166d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 3167d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 3168690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 3169690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 3170690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 3171690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 3172690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 31739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) || 31749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 3175690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 3176690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 317729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 3178690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 3179690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 3180690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 3181690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 3182690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 318329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 3184690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 3185690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 3186690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 3187690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 3188690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 3189690f546b0ee548dbfe997df36418e5302ec2d786James Dong 319025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangconst char *MPEG4Writer::Track::getTrackType() const { 319125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang return mIsAudio ? "Audio" : (mIsVideo ? "Video" : "Metadata"); 319225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang} 31938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 319425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 3195efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 3196b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 3197b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 3198b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 3199b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 3200b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 3201b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 3202b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 3203b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 320425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (mIsVideo) { 3205b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 320625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else { 320725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang writeNmhdBox(); 3208b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3209b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 3210b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 3211b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 3212b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 3213b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 3214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3216b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 3217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 3218b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 3219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 3221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 3222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 322325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (mIsVideo) { 3224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 322525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else { 322625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang writeMetadataFourCCBox(); 3227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 3229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 323025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo) { 323125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang writeCttsBox(); 3232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 3233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 3235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 3236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 3237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 3238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 324025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeMetadataFourCCBox() { 324125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *mime; 324225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang bool success = mMeta->findCString(kKeyMIMEType, &mime); 324325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang CHECK(success); 324425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *fourcc = getFourCCForMime(mime); 324525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (fourcc == NULL) { 324625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("Unknown mime type '%s'.", mime); 324725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang TRESPASS(); 324825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } 324925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->beginBox(fourcc); // TextMetaDataSampleEntry 325025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeCString(mime); // metadata mime_format 325125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->endBox(); // mett 325225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang} 325325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang 3254b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 3255b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 3256b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 3257b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 32588b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 32598b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 326029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 326125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang TRESPASS(); 3262b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3263b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 32648b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan mOwner->beginBox(fourcc); // video format 3265b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3266b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3267b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 3268b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3269b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3270b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 3271b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 3272b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 3273b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3274b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 3275b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 3276b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 3277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3278b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3279b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 3280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 3281b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 3282b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 3283b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3284b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 3285c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->writeInt8(0); // compressor string length 3286c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->write(" ", 31); 3287b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 3288b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 3289b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3290b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 3291b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 3292b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 3293b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 3294b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 3295b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 32969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 32979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim writeHvccBox(); 3298b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3299b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 330158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar writeColrBox(); 3302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 3303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 330558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() { 330658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar ColorAspects aspects; 330758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar memset(&aspects, 0, sizeof(aspects)); 330858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar // TRICKY: using | instead of || because we want to execute all findInt32-s 330958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries) 331058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer) 331158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs) 331258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) { 331358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar int32_t primaries, transfer, coeffs; 331458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar bool fullRange; 331558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar ColorUtils::convertCodecColorAspectsToIsoAspects( 331658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar aspects, &primaries, &transfer, &coeffs, &fullRange); 331758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->beginBox("colr"); 331858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeFourcc("nclx"); 331958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(primaries); 332058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(transfer); 332158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(coeffs); 3322fffb0c8fbe16ac948619b85e1eea9e65a9daa0c9Pirama Arumuga Nainar mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0)); 332358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->endBox(); // colr 332458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar } 332558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar} 332658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar 3327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 3328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 3329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 3330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 33318b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 33328b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 333329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 333425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang TRESPASS(); 3335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 3338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 3341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 3344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 3345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 3346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 3347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 3351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 3352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 3354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 3355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 3356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 3357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 3358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 3359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3360b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3363b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 3364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 3365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 336643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 3367b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 336943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(mCodecSpecificDataSize + 23, 128); 3370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3372b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 3373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 3374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 3375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 3376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 3379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 3380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 3381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 338346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt8(0x00); // buffer size 24-bit (0x300) 338446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 338596bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t avgBitrate = 0; 338646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 338796bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t maxBitrate = 0; 338846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 338946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(maxBitrate); 339046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(avgBitrate); 3391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 3394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 3397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 3398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 3399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 3400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 3402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 3404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 3407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 340843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 3409bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan 3410bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan // Make sure all sizes encode to a single byte. 3411bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan CHECK_LT(23 + mCodecSpecificDataSize, 128); 3412bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan 3413b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 3414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 3418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 3419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 3420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 3421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 3424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 3425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 3426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 342846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 0x01, 0x77, 0x00, // buffer size 96000 bytes 3429b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3430b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 3431b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 343296bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t avgBitrate = 0; 343346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 343496bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t maxBitrate = 0; 343546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 343646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(maxBitrate); 343746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(avgBitrate); 343846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 3439b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3441b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 3442b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3443b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3444b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 3445b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 3446b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 3447b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 3448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3449b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 3450b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3451b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 3452b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3453b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3454efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 3455b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 3456b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 3457b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 3458b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 3459b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 3460b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 3461219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 3462b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 34638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 3464b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 3465b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 3466b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 3467b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 3468b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3469b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3470b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 3471b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 3472b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 3473b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3474b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3475b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 347620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 347725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (!mIsVideo) { 3478b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 3479b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 3480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 3481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 3482467743d462773ada299148ed5a210479affd1f4cHangyu Kuang bool success = mMeta->findInt32(kKeyDisplayWidth, &width); 3483467743d462773ada299148ed5a210479affd1f4cHangyu Kuang success = success && mMeta->findInt32(kKeyDisplayHeight, &height); 3484467743d462773ada299148ed5a210479affd1f4cHangyu Kuang 3485467743d462773ada299148ed5a210479affd1f4cHangyu Kuang // Use width/height if display width/height are not present. 3486467743d462773ada299148ed5a210479affd1f4cHangyu Kuang if (!success) { 3487467743d462773ada299148ed5a210479affd1f4cHangyu Kuang success = mMeta->findInt32(kKeyWidth, &width); 3488467743d462773ada299148ed5a210479affd1f4cHangyu Kuang success = success && mMeta->findInt32(kKeyHeight, &height); 3489467743d462773ada299148ed5a210479affd1f4cHangyu Kuang } 3490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 3493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 3494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 3496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 3499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 3500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 3501b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 3502b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 3503b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 3504b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 3505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3507b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 3509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 3510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 3512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 351625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeNmhdBox() { 351725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->beginBox("nmhd"); 351825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeInt32(0); // version=0, flags=0 351925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->endBox(); 352025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang} 352125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang 3522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 3523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 3524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 352625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeFourcc(mIsAudio ? "soun" : (mIsVideo ? "vide" : "meta")); // component subtype 3527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 353125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeCString(mIsAudio ? "SoundHandle": (mIsVideo ? "VideoHandle" : "MetadHandle")); 3532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3535efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 3536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 35371d515f4b608f1e6592780365857855962c0da725xiahong.bao int64_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 3538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 35391d515f4b608f1e6592780365857855962c0da725xiahong.bao 35401d515f4b608f1e6592780365857855962c0da725xiahong.bao if (mdhdDuration > UINT32_MAX) { 35411d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32((1 << 24)); // version=1, flags=0 35421d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt64((int64_t)now); // creation time 35431d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt64((int64_t)now); // modification time 35441d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32(mTimeScale); // media timescale 35451d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt64(mdhdDuration); // media timescale 35461d515f4b608f1e6592780365857855962c0da725xiahong.bao } else { 35471d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32(0); // version=0, flags=0 35481d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32(now); // creation time 35491d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32(now); // modification time 35501d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32(mTimeScale); // media timescale 35511d515f4b608f1e6592780365857855962c0da725xiahong.bao mOwner->writeInt32((int32_t)mdhdDuration); // use media timescale 35521d515f4b608f1e6592780365857855962c0da725xiahong.bao } 3553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 3554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 3555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 3556b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 3557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 3558decc50efede28c5d73137c30d1a95d72dd405555David Yeh const char *lang = NULL; 3559decc50efede28c5d73137c30d1a95d72dd405555David Yeh int16_t langCode = 0; 3560decc50efede28c5d73137c30d1a95d72dd405555David Yeh if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) { 3561decc50efede28c5d73137c30d1a95d72dd405555David Yeh langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f); 3562decc50efede28c5d73137c30d1a95d72dd405555David Yeh } 3563decc50efede28c5d73137c30d1a95d72dd405555David Yeh mOwner->writeInt16(langCode); // language code 3564b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3565b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 3569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 3570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 3571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 3572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 3574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 3575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 3576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 3580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 3581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 3582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 3583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 3584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 3585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 3588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 3589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 3591b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 3592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 3593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 3596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 3597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 3598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 3599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 3602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 360343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mCodecSpecificDataSize, 5); 3604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 3606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 3607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 3608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 3609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 3610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 3612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 36149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 36159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() { 36169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim CHECK(mCodecSpecificData); 36179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim CHECK_GE(mCodecSpecificDataSize, 5); 36189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 36199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Patch avcc's lengthSize field to match the number 36209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // of bytes we use to indicate the size of a nal unit. 36219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim uint8_t *ptr = (uint8_t *)mCodecSpecificData; 36229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 36239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->beginBox("hvcC"); 36249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 36259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->endBox(); // hvcC 36269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 36279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 3628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 3629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 3630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 3631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 3633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 3634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 3635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 3638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 3639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 3640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 3641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 3642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 3643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3645000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 3646a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 3647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 364943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 3650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3652000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 3653000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 3654000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3655000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 3656000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 3657000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3658c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3659c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mSttsTableEntries->get(duration, 1)); 3660c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back to host byte order 3661c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 3662c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 3663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 3664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 366520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3666965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 3667000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 3668000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 3669000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 3670000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 3671000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3672965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 3673c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 3674965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3675965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3676965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3677a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]", 3678c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 3679965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3680965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 3681000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 36820d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka int64_t delta = mMinCttsOffsetTimeUs - getStartTimeOffsetScaledTime(); 3683c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) { 3684c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar // entries are <count, ctts> pairs; adjust only ctts 3685c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t duration = htonl(value[1]); // back to host byte order 36860d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka // Prevent overflow and underflow 36870d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka if (delta > duration) { 36880d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka duration = 0; 36890d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka } else if (delta < 0 && UINT32_MAX + delta < duration) { 36900d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka duration = UINT32_MAX; 36910d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka } else { 36920d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka duration -= delta; 36930d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka } 36940d3d9531716705787bd2168023a91772163d5e0aMahesh Lanka value[1] = htonl(duration); 3695c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar }); 3696c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 3697965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 3698965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 3699965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 3701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 3702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3703c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 3704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 3705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 370625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 3707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 3708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 3709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3710c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 3711c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 3712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 3713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 371420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 3716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 3717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3718c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 3719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 3720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 372120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 3723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 3724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3725c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 3726c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 3727c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 3728c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 3729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 373120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 373220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 373307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 373407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 373507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 373607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 373707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 373807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 3739e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() { 3740e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("hdlr"); 3741e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3742e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Predefined 3743e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3744e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[0] 3745e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[1] 3746e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[2] 3747e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt8(0); // Name (empty) 3748e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3749e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3750e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3751e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() { 3752e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3753e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3754e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("keys"); 3755e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3756e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(count); // Entry_count 3757e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3758e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3759e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3760e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t n = strlen(key); 3761e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(n + 8); 3762e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3763e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang write(key, n); // write without the \0 3764e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3765e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3766e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3767e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3768e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() { 3769e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3770e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3771e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("ilst"); 3772e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3773e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox(i + 1); // key id (1-based) 3774e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("data"); 3775e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3776e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3777e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang switch (type) { 37787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang case AMessage::kTypeString: 37797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang { 37807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang AString val; 37817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang CHECK(mMetaKeys->findString(key, &val)); 37827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(1); // type = UTF8 37837c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 37847c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang write(val.c_str(), strlen(val.c_str())); // write without \0 37857c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang break; 37867c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 37877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 3788e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeFloat: 3789e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3790e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang float val; 3791e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findFloat(key, &val)); 37927c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(23); // type = float32 37937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3794e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(*reinterpret_cast<int32_t *>(&val)); 3795e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3796e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3797e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3798e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeInt32: 3799e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3800e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang int32_t val; 3801e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findInt32(key, &val)); 38027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(67); // type = signed int32 38037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3804e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(val); 3805e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3806e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3807e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3808e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang default: 3809e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3810e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang ALOGW("Unsupported key type, writing 0 instead"); 38117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(77); // type = unsigned int32 38127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3813e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 3814e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3815e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3816e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3817e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // data 3818e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // key id 3819e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3820e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // ilst 3821e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3822e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3823e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() { 3824e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3825e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (count == 0) { 3826e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return; 3827e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3828e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3829e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("meta"); 3830e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeHdlr(); 3831e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeKeys(); 3832e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeIlst(); 3833e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3834e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3835e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 383607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 383707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 383807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 383907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 384007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 384107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 384207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 384307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 384407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 3845432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 3846432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 384707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 384807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 384907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 385007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 385107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 385207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 385307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 385407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 385520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3856