MPEG4Writer.cpp revision 96626b7f9a4e5c9e1e04f7f710383631d1470364
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"; 753b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#ifdef SHOW_MODEL_BUILD 763b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[] = "com.android.model"; 777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[] = "com.android.build"; 783b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif 797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps"; 804dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatic const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count"; 817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = { 839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeVps, 849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeSps, 859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypePps, 869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}; 879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = { 889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeVps, 899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeSps, 909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypePps, 919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypePrefixSei, 929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeSuffixSei, 939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}; 947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang/* uncomment to include model and build in meta */ 957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1 967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 99b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen Track(MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId); 1008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 10437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t stop(); 10537187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 10625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1083b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 109d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTrackHeader(bool use32BitOffset = true); 1111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 1121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 1139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bool isHevc() const { return mIsHevc; } 1141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 1151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 116c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong void addChunkOffset(off64_t offset); 11770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int32_t getTrackId() const { return mTrackId; } 118dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 1198b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan static const char *getFourCCForMime(const char *mime); 12025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *getTrackType() const; 12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 123000e18370baae60ffd9f25b509501dd8c26deabfJames Dong enum { 124000e18370baae60ffd9f25b509501dd8c26deabfJames Dong kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 1258c460498c028888c533ab442be12b6d4b669b965James Dong kSampleArraySize = 1000, 126000e18370baae60ffd9f25b509501dd8c26deabfJames Dong }; 127000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // A helper class to handle faster write box with table entries 129c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar template<class TYPE, unsigned ENTRY_SIZE> 130c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar // ENTRY_SIZE: # of values in each entry 131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong struct ListTableEntries { 132c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar static_assert(ENTRY_SIZE > 0, "ENTRY_SIZE must be positive"); 133c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries(uint32_t elementCapacity) 134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mElementCapacity(elementCapacity), 135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTotalNumTableEntries(0), 136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry(0), 137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement(NULL) { 138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mElementCapacity, 0); 1392177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia // Ensure no integer overflow on allocation in add(). 140c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar CHECK_LT(ENTRY_SIZE, UINT32_MAX / mElementCapacity); 141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Free the allocated memory. 144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ~ListTableEntries() { 145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (!mTableEntryList.empty()) { 146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete[] (*it); 148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.erase(it); 149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Replace the value at the given position by the given value. 153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // There must be an existing value at the given position. 154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order 155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void set(const TYPE& value, uint32_t pos) { 157c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar CHECK_LT(pos, mTotalNumTableEntries * ENTRY_SIZE); 158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 160c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE)); 161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 168c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar (*it)[(pos % (mElementCapacity * ENTRY_SIZE))] = value; 169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Get the value at the given position by the given value. 172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value the retrieved value at the position in network byte order. 173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @return true if a value is found. 175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool get(TYPE& value, uint32_t pos) const { 176c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar if (pos >= mTotalNumTableEntries * ENTRY_SIZE) { 177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return false; 178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 181c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE)); 182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 189c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar value = (*it)[(pos % (mElementCapacity * ENTRY_SIZE))]; 190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return true; 191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 193c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar // adjusts all values by |adjust(value)| 194c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar void adjustEntries( 195c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar std::function<void(size_t /* ix */, TYPE(& /* entry */)[ENTRY_SIZE])> update) { 196c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar size_t nEntries = mTotalNumTableEntries + mNumValuesInCurrEntry / ENTRY_SIZE; 197c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar size_t ix = 0; 198c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar for (TYPE *entryArray : mTableEntryList) { 199c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar size_t num = std::min(nEntries, (size_t)mElementCapacity); 200c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar for (size_t i = 0; i < num; ++i) { 201c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar update(ix++, (TYPE(&)[ENTRY_SIZE])(*entryArray)); 202c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar entryArray += ENTRY_SIZE; 203c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar } 204c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar nEntries -= num; 205c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar } 206c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar } 207c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar 208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Store a single value. 209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order. 210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void add(const TYPE& value) { 211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 213c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t nValues = mNumValuesInCurrEntry % ENTRY_SIZE; 214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries == 0 && nValues == 0) { 215c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCurrTableEntriesElement = new TYPE[ENTRY_SIZE * mElementCapacity]; 216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCurrTableEntriesElement != NULL); 217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.push_back(mCurrTableEntriesElement); 218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 220c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t pos = nEntries * ENTRY_SIZE + nValues; 221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement[pos] = value; 222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mNumValuesInCurrEntry; 224c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar if ((mNumValuesInCurrEntry % ENTRY_SIZE) == 0) { 225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mTotalNumTableEntries; 226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry = 0; 227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Write out the table entries: 231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 1. the number of entries goes first 232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 2. followed by the values in the table enties in order 233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg writer the writer to actual write to the storage 234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void write(MPEG4Writer *writer) const { 235c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar CHECK_EQ(mNumValuesInCurrEntry % ENTRY_SIZE, 0); 236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries; 237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->writeInt32(nEntries); 238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong it != mTableEntryList.end(); ++it) { 240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(nEntries, 0); 241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries >= mElementCapacity) { 242c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, mElementCapacity); 243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong nEntries -= mElementCapacity; 244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 245c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, nEntries); 246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong break; 247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Return the number of entries in the table. 252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count() const { return mTotalNumTableEntries; } 253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong private: 255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mElementCapacity; // # entries in an element 256c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mTotalNumTableEntries; 257c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t mNumValuesInCurrEntry; // up to ENTRY_SIZE 258c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong TYPE *mCurrTableEntriesElement; 259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mutable List<TYPE *> mTableEntryList; 260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 261c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 262c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong }; 263c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 264c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 265c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 268b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen sp<IMediaSource> mSource; 26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 270a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 271a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 272eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 2731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 2749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bool mIsHevc; 2751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 27625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang bool mIsVideo; 2771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 2789db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang bool mIsMalformed; 279bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 280c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 28143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 282826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar int64_t mLastDecodingTimeUs; 283e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 284d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 2851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 2868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 290be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 29113aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 2921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 293c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool mSamplesHaveSameSize; 294c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 1> *mStszTableEntries; 295be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 296c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 1> *mStcoTableEntries; 297c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<off64_t, 1> *mCo64TableEntries; 298c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 3> *mStscTableEntries; 299c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 1> *mStssTableEntries; 300c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 2> *mSttsTableEntries; 301c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 2> *mCttsTableEntries; 302965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 303000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMinCttsOffsetTimeUs; 304000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMaxCttsOffsetTimeUs; 305965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 3073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 3083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 3093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 3103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 3113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 3123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 3133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 3143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 3153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 3163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 3173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 3183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 3193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 322548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 32393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 3263c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 32770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 32870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 32993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 33093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 33125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 332872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 333872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 334872a481558350634a3fd5cb67939de288af00ecbJames Dong 335000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int32_t getStartTimeOffsetScaledTime() const; 336000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 33837187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 3413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 3423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 3439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0); 3449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 348215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 3499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size); 3509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size); 3519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t parseHEVCCodecSpecificData( 3529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, HevcParameterSets ¶mSets); 3539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 354215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 355faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 35693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 35703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 35819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 35919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 360c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 361c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 362c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 363c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 364c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 365c059860c73678a202bfa33062723e8f82fb779d9James Dong 366690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 367690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 36813f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t mRotation; 369690f546b0ee548dbfe997df36418e5302ec2d786James Dong 3701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 3711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 3721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 37379761ab096f57c3027fad9556c2bc436672d614eJames Dong 37479761ab096f57c3027fad9556c2bc436672d614eJames Dong // Duration is time scale based 37579761ab096f57c3027fad9556c2bc436672d614eJames Dong void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 376965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 37745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 37845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong bool isTrackMalFormed() const; 37943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 3801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 387965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void writeCttsBox(); 388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 3919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim void writeHvccBox(); 392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 396efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeMdhdBox(uint32_t now); 397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 39925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang void writeNmhdBox(); 400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 401efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeTkhdBox(uint32_t now); 40258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar void writeColrBox(); 403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 40725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang void writeMetadataFourCCBox(); 408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 41430ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 415674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(dup(fd)), 416674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(mFd < 0? NO_INIT: OK), 417de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording(true), 418b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 4191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 420a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 421a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 422a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 423411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 42430ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 42513aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 426e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mMoovBoxBuffer(NULL), 427e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mMoovBoxBufferOffset(0), 428e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mWriteMoovBoxToMemory(false), 429e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mFreeBoxOffset(0), 430e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mStreamableFile(false), 4317837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 4327c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize(0), 43307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 434e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mTimeScale(-1), 435e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mStartTimestampUs(-1ll), 43607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 43707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 43825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mHasAudioTrack(false), 43925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mHasVideoTrack(false), 44086b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 441ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar mStartTimeOffsetMs(-1), 442ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar mMetaKeys(new AMessage()) { 4437c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang addDeviceMeta(); 4442aa74dc097fe860abc84769abf2b6e0962718471Robert Shih 4452aa74dc097fe860abc84769abf2b6e0962718471Robert Shih // Verify mFd is seekable 4462aa74dc097fe860abc84769abf2b6e0962718471Robert Shih off64_t off = lseek64(mFd, 0, SEEK_SET); 4472aa74dc097fe860abc84769abf2b6e0962718471Robert Shih if (off < 0) { 4482aa74dc097fe860abc84769abf2b6e0962718471Robert Shih ALOGE("cannot seek mFd: %s (%d)", strerror(errno), errno); 4492aa74dc097fe860abc84769abf2b6e0962718471Robert Shih release(); 4502aa74dc097fe860abc84769abf2b6e0962718471Robert Shih } 45130ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 45230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 45320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 4548bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong reset(); 45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 4571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 4591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 4601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 465dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 466dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 467dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 468dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 469dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 470dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 471dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 472dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 473dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 474dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 475dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 476dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 477dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 478dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 479dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 480dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 481dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 482dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 48384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber int fd, const Vector<String16>& /* args */) const { 484dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 485dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 486dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 48725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang snprintf(buffer, SIZE, " %s track\n", getTrackType()); 488dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 489dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 490dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 491dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 492c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 49313210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 494377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); 49513210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 496dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 497dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 498dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 499dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 5008b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static 5018b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) { 5028b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (mime == NULL) { 5038b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 5048b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 5058b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strncasecmp(mime, "audio/", 6)) { 5068b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 5078b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "samr"; 5088b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 5098b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "sawb"; 5108b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 5118b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4a"; 5128b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 5138b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strncasecmp(mime, "video/", 6)) { 5148b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 5158b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4v"; 5168b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 5178b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "s263"; 5188b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 5198b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "avc1"; 5209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 5219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return "hvc1"; 5228b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 52325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (!strncasecmp(mime, "application/", 12)) { 52425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang return "mett"; 5258b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else { 52625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("Track (%s) other than video/audio/metadata is not supported", mime); 5278b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 5288b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 5298b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan} 5308b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan 531b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissenstatus_t MPEG4Writer::addSource(const sp<IMediaSource> &source) { 532bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 533bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 53429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Attempt to add source AFTER recording is started"); 535bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 536bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 537acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 538acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong CHECK(source.get() != NULL); 539acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 540acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong const char *mime; 541acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong source->getFormat()->findCString(kKeyMIMEType, &mime); 542acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 54325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (!strncasecmp(mime, "audio/", 6)) { 54425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mHasAudioTrack) { 54525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("At most one audio track can be added"); 54625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang return ERROR_UNSUPPORTED; 54725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } 54825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mHasAudioTrack = true; 54925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } 550acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 55125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (!strncasecmp(mime, "video/", 6)) { 55225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mHasVideoTrack) { 55325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("At most one video track can be added"); 554acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 555acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 55625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mHasVideoTrack = true; 557acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 558acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 55925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (Track::getFourCCForMime(mime) == NULL) { 56025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("Unsupported mime '%s'", mime); 56125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang return ERROR_UNSUPPORTED; 56225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } 56325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang 56425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang // This is a metadata track or the first track of either audio or video 565acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // Go ahead to add the track. 566219f195159f93d627af2b243732e3f9020511a46James Dong Track *track = new Track(this, source, 1 + mTracks.size()); 56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 5682dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 5692dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 573acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.empty()) { 574acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("No source added"); 575acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return INVALID_OPERATION; 576acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 577acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 578a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 579a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 58093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 581a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 582a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 583a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 584a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 585a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 586a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 587a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 588a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 589a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 590a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 591a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 592a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 593a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 5947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() { 5957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // add device info and estimate space in 'moov' 5967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang char val[PROPERTY_VALUE_MAX]; 5977c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size_t n; 5987c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // meta size is estimated by adding up the following: 5997c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - meta header structures, which occur only once (total 66 bytes) 6007c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - size for each key, which consists of a fixed header (32 bytes), 6017c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // plus key length and data length. 6027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 66; 6037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.version.release", val, NULL) 6047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 6057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Version, val, n + 1); 6067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32; 6077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 6087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD 6097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.product.model", val, NULL) 6107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 6117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Model, val, n + 1); 6127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32; 6137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 6147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.display.id", val, NULL) 6157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 6167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Build, val, n + 1); 6177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32; 6187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 6197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif 6207c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang} 6217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 6222dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 6232dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 6242dec2b5be2056c6d9428897dc672185872d30d17James Dong // 6252dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 6262dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 6272dec2b5be2056c6d9428897dc672185872d30d17James Dong 62878a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 6292dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 63078a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 6312dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 6322dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 6332dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 6342dec2b5be2056c6d9428897dc672185872d30d17James Dong 6352dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 6362dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 6372dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 63878a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 6392dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 6402dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 6412dec2b5be2056c6d9428897dc672185872d30d17James Dong 64278a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 643a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 64478a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 64578a1a286f736888ae7af8860b2c424af0d978848James Dong } 64678a1a286f736888ae7af8860b2c424af0d978848James Dong 64778a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 64878a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 64978a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 65078a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 6510ca31521644b9396829850f7400d23f9b107cc64Johan Redestig ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000; 65278a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 65378a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 65478a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 65578a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 65678a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 65778a1a286f736888ae7af8860b2c424af0d978848James Dong } 65878a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 65978a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 66078a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 66178a1a286f736888ae7af8860b2c424af0d978848James Dong } 6622dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6632dec2b5be2056c6d9428897dc672185872d30d17James Dong } 66478a1a286f736888ae7af8860b2c424af0d978848James Dong 6652dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 6662dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 6672dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6682dec2b5be2056c6d9428897dc672185872d30d17James Dong 6692dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 6702dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 6712dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 6722dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 6732dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6742dec2b5be2056c6d9428897dc672185872d30d17James Dong 6757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // Account for the extra stuff (Geo, meta keys, etc.) 6767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size += mMoovExtraSize; 6777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 678a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the" 679a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn " estimated moov size %" PRId64 " bytes", 6802dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 6812dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 6822dec2b5be2056c6d9428897dc672185872d30d17James Dong} 6832dec2b5be2056c6d9428897dc672185872d30d17James Dong 6842dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 685674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 68625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 689a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 690a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 691a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 692a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 693a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 694a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 695a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 696a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 697a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 698a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 6992dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 7002dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 7012dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 7022dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 7032dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 7042dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7052dec2b5be2056c6d9428897dc672185872d30d17James Dong 7061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 7071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 7081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 7091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 7101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 7111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 7121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 7131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 7141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 715a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. " 716a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn "It is changed to %" PRId64 " bytes", 717d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 718d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 7191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 7201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 7211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 722b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 723b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 724b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 725b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 726b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 7272dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7282dec2b5be2056c6d9428897dc672185872d30d17James Dong 729de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui int32_t isRealTimeRecording; 730de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) { 731de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording = isRealTimeRecording; 732de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 733de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 734065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 73593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 736a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 737a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 738a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 73993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 740a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 741a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 742a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 743a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 7448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 7458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 7468f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 7478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 74843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 7493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("movie time scale: %d", mTimeScale); 7508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 75177e8ae9967a078770416619e99ddb5b010def312James Dong /* 75277e8ae9967a078770416619e99ddb5b010def312James Dong * When the requested file size limit is small, the priority 75377e8ae9967a078770416619e99ddb5b010def312James Dong * is to meet the file size limit requirement, rather than 7547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to make the file streamable. mStreamableFile does not tell 7557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * whether the actual recorded file is streamable or not. 75677e8ae9967a078770416619e99ddb5b010def312James Dong */ 75777e8ae9967a078770416619e99ddb5b010def312James Dong mStreamableFile = 75877e8ae9967a078770416619e99ddb5b010def312James Dong (mMaxFileSizeLimitBytes != 0 && 75977e8ae9967a078770416619e99ddb5b010def312James Dong mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 76077e8ae9967a078770416619e99ddb5b010def312James Dong 7617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong /* 7627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory is true if the amount of data in moov box is 7637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * smaller than the reserved free space at the beginning of a file, AND 7647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * when the content of moov box is constructed. Note that video/audio 7657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * frame data is always written to the file but not in the memory. 7667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Before stop()/reset() is called, mWriteMoovBoxToMemory is always 7687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * false. When reset() is called at the end of a recording session, 7697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Moov box needs to be constructed. 7707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory 7727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to set to mStreamableFile so that if 7737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the file is intended to be streamable, it is set to true; 7747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * otherwise, it is set to false. When the value is set to false, 7757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * all the content of the moov box is written immediately to 7767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the end of the file. When the value is set to true, all the 7777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * content of the moov box is written to an in-memory cache, 7787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mMoovBoxBuffer, util the following condition happens. Note 7797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * that the size of the in-memory cache is the same as the 7807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * reserved free space at the beginning of the file. 7817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 2) While the data of the moov box is written to an in-memory 7837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache, the data size is checked against the reserved space. 7847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * If the data size surpasses the reserved space, subsequent moov 7857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * data could no longer be hold in the in-memory cache. This also 7867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * indicates that the reserved space was too small. At this point, 7877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * _all_ moov data must be written to the end of the file. 7887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory must be set to false to direct the write 7897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to the file. 7907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 3) If the data size in moov box is smaller than the reserved 7927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space after moov box is completely constructed, the in-memory 7937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache copy of the moov box is written to the reserved free 7947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space. Thus, immediately after the moov is completedly 7957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * constructed, mWriteMoovBoxToMemory is always set to false. 7967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong */ 7977b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 7987837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 7997837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 8007837c17063a4c50bc856ba59418516fdab731de7James Dong 801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 80220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8037837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8057837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 8062dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 8072dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 8082dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 8092dec2b5be2056c6d9428897dc672185872d30d17James Dong } 8102dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 8117837c17063a4c50bc856ba59418516fdab731de7James Dong } 81243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mEstimatedMoovBoxSize, 8); 81377e8ae9967a078770416619e99ddb5b010def312James Dong if (mStreamableFile) { 81477e8ae9967a078770416619e99ddb5b010def312James Dong // Reserve a 'free' box only for streamable file 81577e8ae9967a078770416619e99ddb5b010def312James Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 81677e8ae9967a078770416619e99ddb5b010def312James Dong writeInt32(mEstimatedMoovBoxSize); 81777e8ae9967a078770416619e99ddb5b010def312James Dong write("free", 4); 81877e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 81977e8ae9967a078770416619e99ddb5b010def312James Dong } else { 82077e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mOffset; 82177e8ae9967a078770416619e99ddb5b010def312James Dong } 8227837c17063a4c50bc856ba59418516fdab731de7James Dong 8237837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 824c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 8251acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 8261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 8271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 8281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 8291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 8301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 8321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 8331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 8341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 837a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 838a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 8401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 841a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 84225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 84320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 8461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 8471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 84937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 850674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 85137187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 852a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 853a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 85437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 855a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 856a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 85737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 85837187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 85937187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 86037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 861a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 86237187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 863a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 864a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 8651c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 866b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping writer thread"); 867411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 868411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 869411ba422e3635d534928ffd81abf54f4f291c739James Dong } 8701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 8751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 8761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 8791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 880411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 881b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Writer thread stopped"); 8821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 8831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 88413f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 88513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 88613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 88713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 88813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 88913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 89013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 89113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 89213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 89313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 89413f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 89513f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 8963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeCompositionMatrix"); 89713f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 89813f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 89913f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 90013f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 90113f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 90213f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 90313f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 90413f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 90513f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 90613f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 90713f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 90813f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 90913f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 91013f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 91113f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 91213f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 91313f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 91413f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 91513f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 91613f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 91713f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 91813f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 91913f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 92013f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 92113f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 92213f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 92313f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 92413f6284305e4b27395a23db7882d670bdb1bcae1James Dong 92513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 92613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 92713f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 92813f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 92913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 93013f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 93113f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 93213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 93313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 93413f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 93513f6284305e4b27395a23db7882d670bdb1bcae1James Dong 936411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 937411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 938411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 939411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 940411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 9414c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary free(mMoovBoxBuffer); 9424c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary mMoovBoxBuffer = NULL; 943411ba422e3635d534928ffd81abf54f4f291c739James Dong} 94413f6284305e4b27395a23db7882d670bdb1bcae1James Dong 9458bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() { 946674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 94737187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 948411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 949411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 950411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 951411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 952411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 953411ba422e3635d534928ffd81abf54f4f291c739James Dong } 954411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 955411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 956411ba422e3635d534928ffd81abf54f4f291c739James Dong } 95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 9608f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 96165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 96220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 96437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 96537187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 96637187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 96737187916a486504acaf83bea30147eb5fbf46ae5James Dong } 96820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 9708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 9718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 97365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 97465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 97565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 97665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 97765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 97865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 979a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us", 98065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 9847837c17063a4c50bc856ba59418516fdab731de7James Dong 98537187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 98637187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 987411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 98837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 98937187916a486504acaf83bea30147eb5fbf46ae5James Dong } 99037187916a486504acaf83bea30147eb5fbf46ae5James Dong 99120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 9921acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 993c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 9941f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); 995c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 9961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 997c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 9981f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint64_t size = mOffset - mMdatOffset; 9991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 1000c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 10011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 1002c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 100320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Construct moov box now 10057837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 10067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = mStreamableFile; 10077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 10087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // There is no need to allocate in-memory cache 10097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // for moov box if the file is not streamable. 10107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 10117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 10127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong CHECK(mMoovBoxBuffer != NULL); 10137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 1014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 101520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // mWriteMoovBoxToMemory could be set to false in 10177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // MPEG4Writer::write() method 10187b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 10197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 10207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Content of the moov box is saved in the cache, and the in-memory 10217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // moov box needs to be written to the file in a single shot. 10227b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 102343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 10247837c17063a4c50bc856ba59418516fdab731de7James Dong 10257837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 1026c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 10277837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 1028674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 10297837c17063a4c50bc856ba59418516fdab731de7James Dong 10307837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 1031c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 10327837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 10337837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 10347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } else { 10357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ALOGI("The mp4 file will not be streamable."); 10367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 10377837c17063a4c50bc856ba59418516fdab731de7James Dong 10387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Free in-memory cache for moov box 10397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mMoovBoxBuffer != NULL) { 10407837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 10417837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 10427837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 10437837c17063a4c50bc856ba59418516fdab731de7James Dong } 10447837c17063a4c50bc856ba59418516fdab731de7James Dong 10450c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1047411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 104837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 104920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 105020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1051efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() { 1052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 1053efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 1054efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // while time function returns Unix epoch values which starts 1055efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // at 1970-01-01. Lets add the number of seconds between them 10562b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60); 10572b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen if (now < 0 || uint32_t(now) > UINT32_MAX - delta) { 10582b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen return 0; 10592b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen } 10602b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen uint32_t mpeg4Time = uint32_t(now) + delta; 1061efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson return mpeg4Time; 1062efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson} 1063efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson 1064efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 1065efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 1066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 1067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 1068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 1069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 1070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 1071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 1072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 1073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 1074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 1075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 1076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 1079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1085b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 1086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 1087b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1088b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1089b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 1090b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 1091b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 109207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 109307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 109407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 1095e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeMetaBox(); 1096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 1097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 1098b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 1099b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 1100b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 1102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 11042cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 1105b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 1106b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 1108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 1109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 1110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 11118284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 11128284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("isom"); 11138284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("3gp4"); 1114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 11158284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 11168284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 1117b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 11188284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 1119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1120b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 1122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1123b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 112407ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 112507ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 112607ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 112707ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 112807ec01904613a0bac32caaa8444b4690998faed7James Dong 112907ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 113007ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 113196626b7f9a4e5c9e1e04f7f710383631d1470364Marco Nelissen if (property_get_bool("rw.media.record.test", false)) { 113207ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 113307ec01904613a0bac32caaa8444b4690998faed7James Dong } 113407ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 113507ec01904613a0bac32caaa8444b4690998faed7James Dong} 113607ec01904613a0bac32caaa8444b4690998faed7James Dong 113770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 113807ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 113907ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 114007ec01904613a0bac32caaa8444b4690998faed7James Dong return; 114107ec01904613a0bac32caaa8444b4690998faed7James Dong } 114207ec01904613a0bac32caaa8444b4690998faed7James Dong 114370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 114470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 114570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 114670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 114770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 114870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 114970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 115070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 115170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 115213aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 115313aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 115413aec890216948b0c364f8f92792129d0335f506James Dong return OK; 115513aec890216948b0c364f8f92792129d0335f506James Dong} 115613aec890216948b0c364f8f92792129d0335f506James Dong 115713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 115813aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 115913aec890216948b0c364f8f92792129d0335f506James Dong} 116013aec890216948b0c364f8f92792129d0335f506James Dong 116113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 116213aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 116313aec890216948b0c364f8f92792129d0335f506James Dong} 116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1165c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 1166c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1168c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1169c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1170c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 117803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 117903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 118003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 118103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 118203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 118303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 118403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 118503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 118603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 118703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 118803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 118903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 119003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 119180f78b773f92048944a850efb7b60629643370cdPraveen Chavanoff64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) { 119280f78b773f92048944a850efb7b60629643370cdPraveen Chavan off64_t old_offset = mOffset; 119380f78b773f92048944a850efb7b60629643370cdPraveen Chavan 119480f78b773f92048944a850efb7b60629643370cdPraveen Chavan const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs 119580f78b773f92048944a850efb7b60629643370cdPraveen Chavan 119680f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset(); 119780f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *currentNalStart = dataStart; 119880f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *nextNalStart; 119980f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *data = dataStart; 120080f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t nextNalSize; 120180f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ? 120280f78b773f92048944a850efb7b60629643370cdPraveen Chavan kExtensionNALSearchRange : buffer->range_length(); 120380f78b773f92048944a850efb7b60629643370cdPraveen Chavan 120480f78b773f92048944a850efb7b60629643370cdPraveen Chavan while (getNextNALUnit(&data, &searchSize, &nextNalStart, 120580f78b773f92048944a850efb7b60629643370cdPraveen Chavan &nextNalSize, true) == OK) { 120610cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */; 120780f78b773f92048944a850efb7b60629643370cdPraveen Chavan MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize); 120880f78b773f92048944a850efb7b60629643370cdPraveen Chavan addLengthPrefixedSample_l(nalBuf); 120980f78b773f92048944a850efb7b60629643370cdPraveen Chavan nalBuf->release(); 121080f78b773f92048944a850efb7b60629643370cdPraveen Chavan 121180f78b773f92048944a850efb7b60629643370cdPraveen Chavan currentNalStart = nextNalStart; 121280f78b773f92048944a850efb7b60629643370cdPraveen Chavan } 121380f78b773f92048944a850efb7b60629643370cdPraveen Chavan 121480f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t currentNalOffset = currentNalStart - dataStart; 121580f78b773f92048944a850efb7b60629643370cdPraveen Chavan buffer->set_range(buffer->range_offset() + currentNalOffset, 121680f78b773f92048944a850efb7b60629643370cdPraveen Chavan buffer->range_length() - currentNalOffset); 121780f78b773f92048944a850efb7b60629643370cdPraveen Chavan addLengthPrefixedSample_l(buffer); 121880f78b773f92048944a850efb7b60629643370cdPraveen Chavan 121980f78b773f92048944a850efb7b60629643370cdPraveen Chavan return old_offset; 122080f78b773f92048944a850efb7b60629643370cdPraveen Chavan} 122180f78b773f92048944a850efb7b60629643370cdPraveen Chavan 1222c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 1223c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 122430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 122530ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 122603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1227b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 1228b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 1229c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1230b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 1231c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1232b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 1233c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1234b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1235c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1236c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 1237c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1238c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1239c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 1240b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1241b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 1242b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 124343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(length, 65536); 124430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1245b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 1246c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1247b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1248c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1249c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1250b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 1251b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 125230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 125330ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 125430ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 125530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 12567837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 1257674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 12587837c17063a4c50bc856ba59418516fdab731de7James Dong 12597837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 12607837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 12617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 1262c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 12631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 12647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // The reserved moov box at the beginning of the file 12657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // is not big enough. Moov box should be written to 12667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the end of the file from now on, but not to the 12677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // in-memory cache. 12687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 12697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // We write partial moov box that is in the memory to 12707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the file first. 1271c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 12727837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 12737837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 12747837c17063a4c50bc856ba59418516fdab731de7James Dong } 1275674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 1276674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 12777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ::write(mFd, ptr, bytes); 12787837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 12797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 12807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // All subsequent moov box content will be written 12817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // to the end of the file. 12827837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 12837837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 12847837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 12857837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 12867837c17063a4c50bc856ba59418516fdab731de7James Dong } 12877837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1288674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 12897837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 12907837c17063a4c50bc856ba59418516fdab731de7James Dong } 12917837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 12927837c17063a4c50bc856ba59418516fdab731de7James Dong} 12937837c17063a4c50bc856ba59418516fdab731de7James Dong 1294e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) { 1295e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mBoxes.push_back(mWriteMoovBoxToMemory? 1296e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mMoovBoxBufferOffset: mOffset); 1297e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 1298e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 1299e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(id); 1300e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1301e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 130220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 13030c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13057837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 13067837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 130920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 131020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 13130c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1315c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13187837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 13197837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 13207837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 13217837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1322c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 13237837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 13247837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1325c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 13267837c17063a4c50bc856ba59418516fdab731de7James Dong } 132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1330674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1335674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1340674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1345674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1350674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 13540c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 1355674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 135907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 136007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 136107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 136207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 136307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 136407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 136507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 136607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 136707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 136807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 136907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 137007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 137107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 137207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 137307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 137407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 137507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 137607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 137707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 137807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 137907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 138007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 138107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 138207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 138307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 138407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 138507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 138607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 138707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 138807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 138907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 139007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 139107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 139207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 139307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 139407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 139507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 139607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 139707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 139807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 139907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 140007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 140107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 140207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 140307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 140407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 140507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 140607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 140707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 140807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 140907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 141007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 141107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 141207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 141307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 141407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 141507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 141607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 141707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 141807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 141907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 142007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 142107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 142207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 142307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 142407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 142507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 14267c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 30; 142707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 142807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 142907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 1430e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) { 1431e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (captureFps <= 0.0f) { 1432e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return BAD_VALUE; 1433e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 1434e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 14357c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps); 14367c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32; 14377c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 1438e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return OK; 1439e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1440e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 14414dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) { 14424dbff11975e737482537e1636051690188f3fbc4Praveen Chavan if (layerCount > 9) { 14434dbff11975e737482537e1636051690188f3fbc4Praveen Chavan return BAD_VALUE; 14444dbff11975e737482537e1636051690188f3fbc4Praveen Chavan } 14454dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 14464dbff11975e737482537e1636051690188f3fbc4Praveen Chavan if (layerCount > 0) { 14474dbff11975e737482537e1636051690188f3fbc4Praveen Chavan mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount); 14484dbff11975e737482537e1636051690188f3fbc4Praveen Chavan mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32; 14494dbff11975e737482537e1636051690188f3fbc4Praveen Chavan } 14504dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 14514dbff11975e737482537e1636051690188f3fbc4Praveen Chavan return OK; 14524dbff11975e737482537e1636051690188f3fbc4Praveen Chavan} 14534dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 145420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1455674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 145720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 145878a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 145978a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 146078a1a286f736888ae7af8860b2c424af0d978848James Dong} 146178a1a286f736888ae7af8860b2c424af0d978848James Dong 1462d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1463d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1464d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1465d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1466d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1467d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1468956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1469d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1470d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1471d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1472d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 14731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 147477e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 147577e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 147677e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 147777e8ae9967a078770416619e99ddb5b010def312James Dong } 1478acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1479acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1480acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1481acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1482d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1483d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1484d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1485d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1486d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1487d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1488d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1489d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1490d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1491d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1492d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1493d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1494d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1495d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1496d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1497d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1498d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 149925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 150025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 150125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 150225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 150325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 150425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 150525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 150625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 150725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 150825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 150925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 151025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 151125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1512f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1513a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("setStartTimestampUs: %" PRId64, timeUs); 151443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 15153c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1516065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1517f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1518a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs); 15193c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 15203c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 15213c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1522f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 15233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 15243c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 15253c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 15263c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 152758ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 152858ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 152958ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 153058ae9c530247668f8af36e30d228c716c226b3d4James Dong} 153158ae9c530247668f8af36e30d228c716c226b3d4James Dong 153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 153420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1535b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId) 153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 153725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1540a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1541a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1542eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 15439db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed(false), 1544bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1545c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1546956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1547be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1548c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1549c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1550c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)), 1551c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)), 1552c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1553c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)), 1554c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)), 155520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 155625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1557548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 155813f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 155913f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 156019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 15618f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 15621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 15631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 15641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 15659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC); 15661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 156725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mIsVideo = !strncasecmp(mime, "video/", 6); 15681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 15691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 15701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1571b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar // store temporal layer count 157225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo) { 1573b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar int32_t count; 1574b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) { 1575b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar mOwner->setTemporalLayerCount(count); 1576b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar } 1577b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar } 1578b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar 1579c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1580c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1581c059860c73678a202bfa33062723e8f82fb779d9James Dong 15821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 15831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1584c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1585c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 1586c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 1587c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1588c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 15891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 159078a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 159178a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 159278a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 159378a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1594c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1595c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1596c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1597c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 159878a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 159978a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 160078a1a286f736888ae7af8860b2c424af0d978848James Dong } 16011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 16021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 16031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 16041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 16051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1606c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(chunkId)); 1607c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(sampleId)); 1608c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(1)); 16091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 16101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 16111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1612c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 16131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 16141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 16151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 161679761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 16171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 16185a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 1619377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGW("0-duration samples found: %zu", sampleCount); 16205a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1621c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1622c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 16231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 16241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1625965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1626965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1627965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 162825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (!mIsVideo) { 1629965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1630965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1631c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1632c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1633965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1634965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1635c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1636c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1637c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1638c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1639c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1640c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1641c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 16421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 16431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1644c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 16453856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 1646c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1647c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1648c059860c73678a202bfa33062723e8f82fb779d9James Dong 1649c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1650c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1651c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1652c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1653c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1654c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1655c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1656c059860c73678a202bfa33062723e8f82fb779d9James Dong 1657c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1658c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1659c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1660c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1661c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1662c059860c73678a202bfa33062723e8f82fb779d9James Dong 166343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 166419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 166519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 166619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 166719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 166819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 166919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 16709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim uint32_t type; 16719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const void *data = NULL; 16729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t size = 0; 167319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 16749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mMeta->findData(kKeyAVCC, &type, &data, &size); 16759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) { 16769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mMeta->findData(kKeyHVCC, &type, &data, &size); 167719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 167819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 167919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 168019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 16819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (esds.getCodecSpecificInfo(&data, &size) != OK) { 16829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim data = NULL; 16839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size = 0; 168419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 168519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 168619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 16879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) { 16889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mGotAllCodecSpecificData = true; 16899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 169020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 169120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 169220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 169320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 169420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1695c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 1696c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 1697c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 1698c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 1699c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 1700c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 1701c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 1702c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 1703c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 1704c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 1705c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 1706c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 1707c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 1708c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 1709c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 1710c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 171120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 171220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 171320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 171420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 171520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 171620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 171793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 17183856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 171993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 172093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 172193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 172293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 172393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 172493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 1725a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs); 172693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 172793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 172893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 172993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 173093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 173193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 17321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 17331c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 17343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 17351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 17361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 17371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 17381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17401c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 17413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 17421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 17431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 17441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 17461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 17471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 17491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 17501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 17511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 17521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 175543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 17561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1758fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1759a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("writeChunkToFile: %" PRId64 " from %s track", 176025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang chunk->mTimeStampUs, chunk->mTrack->getTrackType()); 1761fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1762fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1763fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1764fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1765fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 17669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc()) 176780f78b773f92048944a850efb7b60629643370cdPraveen Chavan ? addMultipleLengthPrefixedSamples_l(*it) 1768fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1769fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1770fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1771fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1772fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 17731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 17761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1777fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 17781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1779fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 17801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1782fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 17833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 17841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 178570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 178670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1787e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 178870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 17891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 179070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 179170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 179270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 17931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 1794377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGD("%zu chunks are written in the last batch", outstandingChunks); 17951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1797fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 17983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 17991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 18011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 18021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 18031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 18041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 18051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 18061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 18071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 18081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 18091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 18101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 18111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 18121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 18143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 1815fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 18161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 18171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 18191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 18201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1821fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 18221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 18231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 18241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1825fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1826fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1827fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 182870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 182970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 183070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 183170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 183270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 183370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 183470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1835fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 18361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 18371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1838fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1839fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 18401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 18411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18421c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 18433856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 18441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1845a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1846fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1847fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 18481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1849fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1850fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1851fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1852fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 18531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 18541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 18551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1856de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // In real time recording mode, write without holding the lock in order 1857de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // to reduce the blocking time for media track threads. 1858de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // Otherwise, hold the lock until the existing chunks get written to the 1859de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // file. 1860fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 1861de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1862de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.unlock(); 1863de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1864fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 1865de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1866de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.lock(); 1867de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1868fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 18691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1870fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1871fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 18721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 18731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18741c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 18753856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 18761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 18781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1879e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 18801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 18811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 18821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 18831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 188470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 188570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 18861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 18871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 18881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 18901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 18911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 18921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 18931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 1894411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 18951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 18961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 18971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 189993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1900a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1901a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1902a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1903a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1904a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 190525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 190693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 190719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 190819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 190919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 191070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 191119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 191213f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 191325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 191413f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 191513f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 191613f6284305e4b27395a23db7882d670bdb1bcae1James Dong 191793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 191893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1919f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1920de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 1921a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 1922a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 1923a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 1924a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 1925a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 1926a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 192786b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 192886b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 1929a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 193086b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 193186b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 193286b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 193386b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 193486b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 1935a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs); 1936a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 1937a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1938f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1939a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1940f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 194125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 194225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 194325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 194425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 194520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 194620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 194720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 194820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 194920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 195020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1951eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 1952c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 195325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1954956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 19551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 195643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 1957826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar mLastDecodingTimeUs = -1; 195820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 195925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 196020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 196125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 196225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 196320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 196420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 196537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1966a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 196737187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1968a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1969a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 197037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 197125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGD("%s track stopping", getTrackType()); 1972eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 197329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 1974eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 1975eaae38445a340c4857c1c5569475879a728e63b7James Dong } 1976eaae38445a340c4857c1c5569475879a728e63b7James Dong 197720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 197837187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 197920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 198020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 198120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 198225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGD("%s track source stopping", getTrackType()); 198372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mSource->stop(); 198425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGD("%s track source stopped", getTrackType()); 198572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 198620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 198720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 1988377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 198937187916a486504acaf83bea30147eb5fbf46ae5James Dong 199025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGD("%s track stopped", getTrackType()); 199137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 199220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 199320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 199425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 199525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 199625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 199725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 199820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 199920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 200020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 200120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 200237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 2003377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT return (void *)(uintptr_t)err; 200420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 200520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 20073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 20113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 20123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 20193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 202047d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar const uint8_t *nextStartCode = findNextNalStartCode(data, length); 20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 202329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 20243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 20283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 20293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 203029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 20313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 20323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 20343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 20353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 20363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 20373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 20383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 204107b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar // COULD DO: set profile/level to the lowest required to support all SPSs 204229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 20443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 20473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 20483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 20493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 20513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 20523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 20543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 20553856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 20563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 20583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 20599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyCodecSpecificData(data, size, 4 + 7); 20609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 20619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 20629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData( 20639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size) { 20649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGV("copyHEVCCodecSpecificData"); 20659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 20669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2) 20679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyCodecSpecificData(data, size, 23); 20689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 20699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 20709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData( 20719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, size_t minLength) { 20729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (size < minLength) { 2073377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 20743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 20789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 20799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 20809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 20819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 20829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = size; 20833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 20843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 20853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 20863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 20883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 20913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 20923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 20933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 20943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 20953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 20963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 20973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 20983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 20993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 21003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 21013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 21023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 21033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 21043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 21053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 210629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 21073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 21083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 21103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 21113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 21133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 21143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 211529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 21163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 21173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 21193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 21203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 21223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 212329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 21243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 21253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 21283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 21293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 21323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 21333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 21343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 21353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 21383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 21393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 21403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 214129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 21423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 21433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 2146377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 21473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 21483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 21523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 21533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 21543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 215529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 21563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 21573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 2159377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 21603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 21613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21631374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 21641374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 21651374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 21661374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 21673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 21683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 21693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 21703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 21713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 217229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 21733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 21743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21761374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 21773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 21783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 2179548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 218003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 218103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 2182548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 218303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 218429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 218503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 218603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 218703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 21883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 2189377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 219003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 219103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 219203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 21933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 21943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 21953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 219603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 219703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 21983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 219903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 220003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 220103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 22023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 22033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 220403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 22059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 22069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = 0; 22079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 22089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 22099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 221003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 22113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 22123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 22133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 22143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 221503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 22163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2217b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2218b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 2219b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2220b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 2221b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 222203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 22233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 22243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 22253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 22263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 22273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 22283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 22293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 22303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 22313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 22323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 22333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 22353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 22363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 22373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 22403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 22413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 22423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 22433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 22443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 22453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 22463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 22473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 22483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 22493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 22513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 22523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 22533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 225403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 225503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 225603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 225703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 22589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData( 22609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, HevcParameterSets ¶mSets) { 22619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGV("parseHEVCCodecSpecificData"); 22639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *tmp = data; 22649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *nextStartCode = data; 22659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t bytesLeft = size; 22669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 226747d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4); 22689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4); 22699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (err != OK) { 22709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 22719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Move on to find the next parameter set 22749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bytesLeft -= nextStartCode - tmp; 22759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim tmp = nextStartCode; 22769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t csdSize = 23; 22799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const size_t numNalUnits = paramSets.getNumNalUnits(); 22809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) { 22819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim int type = kMandatoryHevcNalUnitTypes[i]; 22829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 22839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (numParamSets == 0) { 22849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Cound not find NAL unit of type %d", type); 22859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 22869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) { 22899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim int type = kHevcNalUnitTypes[i]; 22909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 22919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (numParamSets > 0xffff) { 22929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Too many seq parameter sets (%zu) found", numParamSets); 22939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 22949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim csdSize += 3; 22969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t j = 0; j < numNalUnits; ++j) { 22979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (paramSets.getType(j) != type) { 22989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim continue; 22999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 23009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim csdSize += 2 + paramSets.getSize(j); 23019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 23029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 23039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = csdSize; 23049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return OK; 23059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 23069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 23079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData( 23089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size) { 23099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 23109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData != NULL) { 23119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Already have codec specific data"); 23129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 23139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 23149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 23159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (size < 4) { 23169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Codec specific data length too short: %zu", size); 23179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 23189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 23199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 23209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Data is in the form of HEVCCodecSpecificData 23219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (memcmp("\x00\x00\x00\x01", data, 4)) { 23229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyHEVCCodecSpecificData(data, size); 23239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 23249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 23259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim HevcParameterSets paramSets; 23269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) { 23273d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim ALOGE("failed parsing codec specific data"); 23289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 23299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 23309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 23319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificData = malloc(mCodecSpecificDataSize); 23329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 23339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = 0; 23349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 23359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 23369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 23379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData, 23383d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2); 23399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (err != OK) { 23403d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim ALOGE("failed constructing HVCC atom"); 23419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return err; 23429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 23439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 23449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return OK; 23459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 23469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 2347872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 2348872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 2349872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 2350872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 2351872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 2352872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2353872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 2354872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 2355872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2356872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 2357872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2358872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2359872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2360872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 2361872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2362872a481558350634a3fd5cb67939de288af00ecbJames Dong} 2363872a481558350634a3fd5cb67939de288af00ecbJames Dong 236437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 236530ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 236613aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 236743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 236813aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 236913aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 23707c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar int32_t nActualFrames = 0; // frames containing non-CSD data (non-0 length) 237113aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 2372965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 2373965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 2374965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 2375965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 2376965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 2377000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 2378a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 2379965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 2380000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 2381000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2382000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 238343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2384c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 2385e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2386a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 2387a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 238825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (mIsVideo) { 2389a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 239025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else { 239125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0); 2392a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 2393de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2394de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2395de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2396de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2397985f838934510983d8a887461e98dca60a6e858fJames Dong 2398d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 239920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 240093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 240120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 240225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *trackName = getTrackType(); 240393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 240420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 240520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 240620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 240713aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 240820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 240920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 241020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2411a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 2412a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 2413a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2414a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2415a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2416a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2417a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2418a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2419a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 242030ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 242130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 242203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 242303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 242403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 24257c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // if config format (at track addition) already had CSD, keep that 24267c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // UNLESS we have not received any frames yet. 24277c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // TODO: for now the entire CSD has to come in one frame for encoders, even though 24287c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // they need to be spread out for decoders. 24297c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar if (mGotAllCodecSpecificData && nActualFrames > 0) { 24307c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar ALOGI("ignoring additional CSD for video track after first frame"); 24317c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else { 24327c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar mMeta = mSource->getFormat(); // get output format after format change 24337c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar 24347c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar if (mIsAvc) { 24357c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar status_t err = makeAVCCodecSpecificData( 24367c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar (const uint8_t *)buffer->data() 24377c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar + buffer->range_offset(), 24387c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 24397c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar CHECK_EQ((status_t)OK, err); 24407c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else if (mIsHevc) { 24417c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar status_t err = makeHEVCCodecSpecificData( 24427c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar (const uint8_t *)buffer->data() 24437c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar + buffer->range_offset(), 24447c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 24457c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar CHECK_EQ((status_t)OK, err); 24467c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else if (mIsMPEG4) { 24477c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(), 24487c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 24497c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } 245030ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 245130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 245230ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 245330ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 245430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2455548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 245630ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2457a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2458a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2459e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang // Per-frame metadata sample's size must be smaller than max allowed. 2460e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang if (!mIsVideo && !mIsAudio && buffer->range_length() >= kMaxMetadataSize) { 2461e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang ALOGW("Buffer size is %zu. Maximum metadata buffer size is %lld for %s track", 2462e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang buffer->range_length(), (long long)kMaxMetadataSize, trackName); 2463e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang buffer->release(); 2464e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang mSource->stop(); 2465e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang mIsMalformed = true; 2466e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang break; 2467e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang } 2468e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang 24697c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar ++nActualFrames; 24707c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar 2471d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2472d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2473d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2474d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2475d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2476d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2477d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2478d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2479d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2480d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 24819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mIsAvc || mIsHevc) StripStartcode(copy); 2482e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2483b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 24849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mIsAvc || mIsHevc) { 2485b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2486b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2487b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2488b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2489b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2490b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2491050b28a593350047845a45a14cc5026221ac1620James Dong 2492d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 24931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 24941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 24951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2496d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2497316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang ALOGW("Recorded file size exceeds limit %" PRId64 "bytes", 2498316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang mOwner->mMaxFileSizeLimitBytes); 2499d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2500d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang copy->release(); 2501d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 2502d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2503d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2504d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2505316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds", 2506316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang mOwner->mMaxFileDurationLimitUs); 2507d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2508d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang copy->release(); 2509d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 2510d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2511d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2512d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2513050b28a593350047845a45a14cc5026221ac1620James Dong 2514d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2515d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2516d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2517d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2518d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2519c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 252070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2521f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2522f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 25238428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 25243c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 252548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2526a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 25278428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 252811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) { 252911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2530d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 25319db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 25329db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 253311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 253411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 25358428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 253611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) { 253711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2538d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 25399db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 25409db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 254111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 254211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 25438428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2544a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2545a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2546a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2547a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 254811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 254911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2550d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 25519db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 25529db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 255311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 255411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 255525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo) { 2556965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2557965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2558965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2559000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 2560965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 2561965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 2562965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2563965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 2564826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar 2565826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar // ensure non-negative, monotonic decoding time 2566826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar if (mLastDecodingTimeUs < 0) { 2567826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar decodingTimeUs = std::max((int64_t)0, decodingTimeUs); 2568826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar } else { 2569826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar // increase decoding time by at least 1 tick 2570826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar decodingTimeUs = std::max( 2571826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar mLastDecodingTimeUs + divUp(1000000, mTimeScale), decodingTimeUs); 2572826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar } 2573826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar 2574826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar mLastDecodingTimeUs = decodingTimeUs; 2575000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 2576000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 257711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) { 257811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2579d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 25809db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 25819db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 258211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 258311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2584965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 2585a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64, 2586000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 2587000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2588000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 2589000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 2590000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 259111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) { 259211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2593d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 25949db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 25959db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 259611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 259711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2598c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 259943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 260043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 260143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 260243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 260343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 260443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 260543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 260643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 260743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 260843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 260943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 261043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 261143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 261243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 261343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 2614000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2615000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 2616c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 2617000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2618000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2619000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 2620000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2621000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2622000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2623000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2624000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2625000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2626000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2627965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2628872a481558350634a3fd5cb67939de288af00ecbJames Dong 2629de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2630872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2631872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 2632e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2633e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2634872a481558350634a3fd5cb67939de288af00ecbJames Dong 263511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 263611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2637d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 26389db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 26399db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 264011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 264111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2642a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64, 264311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, previousPausedDurationUs); 2644c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2645c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 26463b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 26473b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 26485a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 26495a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 26505a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 26515a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 26525a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 26535a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 26545a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 26555a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2656c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 2657f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track", 2658f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang (long long)timestampUs, (long long)lastTimestampUs, trackName); 265911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 26600332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang mSource->stop(); 26619db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 26629db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 26638c460498c028888c533ab442be12b6d4b669b965James Dong } 26648c460498c028888c533ab442be12b6d4b669b965James Dong 266585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // if the duration is different for this sample, see if it is close enough to the previous 266685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // duration that we can fudge it and use the same value, to avoid filling the stts table 266785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // with lots of near-identical entries. 266885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // "close enough" here means that the current duration needs to be adjusted by less 266985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // than 0.1 milliseconds 267085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { 267185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL 267285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen + (mTimeScale / 2)) / mTimeScale; 267385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (deltaUs > -100 && deltaUs < 100) { 267485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // use previous ticks, and adjust timestamp as if it was actually that number 267585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // of ticks 267685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen currDurationTicks = lastDurationTicks; 267785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen timestampUs += deltaUs; 267885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 267985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 2680c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 2681c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 2682c059860c73678a202bfa33062723e8f82fb779d9James Dong 2683a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2684a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2685c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 268679761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2687be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2688be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2689be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2690be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2691965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2692be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2693be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2694c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2695be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2696be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 26978644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2698be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2699a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64, 270011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, lastTimestampUs); 27018644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2702c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 27038644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 270420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2705d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 2706c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 2707d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2708d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 270993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 271093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 271193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 271293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2713faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 271493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 271543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 271680f78b773f92048944a850efb7b60629643370cdPraveen Chavan off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy) 271758ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 2718c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2719c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count = (mOwner->use32BitFileOffset() 2720c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 2721c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 2722c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2723c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (count == 0) { 27241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 272558ae9c530247668f8af36e30d228c716c226b3d4James Dong } 272658ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 272758ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 272858ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 272958ae9c530247668f8af36e30d228c716c226b3d4James Dong } 273013aec890216948b0c364f8f92792129d0335f506James Dong 273113aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 273213aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 27331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 27341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 273513aec890216948b0c364f8f92792129d0335f506James Dong } else { 273613aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 273713aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 273813aec890216948b0c364f8f92792129d0335f506James Dong } else { 273943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 274043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 274143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 274243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 274343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 274413aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 274513aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 2746c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 2747c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 2748c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 274913aec890216948b0c364f8f92792129d0335f506James Dong } 27501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 275113aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 275213aec890216948b0c364f8f92792129d0335f506James Dong } 275313aec890216948b0c364f8f92792129d0335f506James Dong } 275413aec890216948b0c364f8f92792129d0335f506James Dong } 275513aec890216948b0c364f8f92792129d0335f506James Dong 275620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 275725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 275845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 2759690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2760f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 276145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2762bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2763be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 276413aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 276543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2766c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(1, mStszTableEntries->count()); 276758ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 27681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 27691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 277013aec890216948b0c364f8f92792129d0335f506James Dong } 277113aec890216948b0c364f8f92792129d0335f506James Dong 2772be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2773be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2774be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2775c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 1) { 27768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 277779761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2778be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2779be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2780be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2781a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2782c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() <= 2) { 278379761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2784a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 278579761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2786a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2787a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 278879761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2789a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2790a472613aec322e25891abf5c77bf3f7e3c244920James Dong 279143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // The last ctts box may not have been written yet, and this 279243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // is to make sure that we write out the last ctts box. 279343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 279443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (cttsSampleCount > 0) { 279543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 279643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 279743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 279843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 2799c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 280025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 280143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 280243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 280343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2804df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 280511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih count, nZeroLengthFrames, mStszTableEntries->count(), trackName); 2806872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2807a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs()); 2808872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2809365a963142093a1cd8efdcea76b5f65096a5b115James Dong 281037187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 281137187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 281237187916a486504acaf83bea30147eb5fbf46ae5James Dong } 281337187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2814365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2815365a963142093a1cd8efdcea76b5f65096a5b115James Dong 281645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 28179db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang if (mIsMalformed) { 28189db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang return true; 28199db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang } 28209db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang 2821c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { // no samples written 282229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 282345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 282445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 282545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 282625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo && mStssTableEntries->count() == 0) { // no sync frames for video 282729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 282845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 282945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 283045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 283145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 283245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 283345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 283445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 283545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 283645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 283745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 283843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 283907ec01904613a0bac32caaa8444b4690998faed7James Dong 284007ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 284107ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 284207ec01904613a0bac32caaa8444b4690998faed7James Dong return; 284307ec01904613a0bac32caaa8444b4690998faed7James Dong } 284407ec01904613a0bac32caaa8444b4690998faed7James Dong 284543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 284643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 284743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 284843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 284925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mIsAudio ? 0: 1); 285043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 285143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 285243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 285343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 285443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 285543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 285643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2857c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 285843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 285986b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 286086b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 286186b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 286286b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 286386b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 286486b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 286586b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 286686b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 286786b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 286886b7f47aa7482424cf8fd248f1315311919be3b0James Dong 286986b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 287070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 287170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 287286b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 287370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 287407ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 287507ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 287607ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 287707ec01904613a0bac32caaa8444b4690998faed7James Dong 287843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 287943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 288043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 288143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 288270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 288370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 288470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 288570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 288670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 288770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 288870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 288970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 289043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 289143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 289243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2893faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 2894a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("trackProgressStatus: %" PRId64 " us", timeUs); 2895c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2896215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 2897215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 2898a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs); 2899bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 290093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 290193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 290293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 290393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2904faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 2905bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 2906faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 2907bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 2908faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2909faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 2910faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 2911faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 2912bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2913bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2914faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2915faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 2916faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2917faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2918faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 2919faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 2920bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2921bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2922faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2923faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 2924faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 2925bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2926bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2927faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 2928faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2929faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 2930faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2931d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 2932a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs); 2933e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2934d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 2935e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2936e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2937e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 2938a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs); 2939e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2940e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 2941e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2942e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2943de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const { 2944de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui return mIsRealTimeRecording; 2945de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui} 2946de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2947b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 2948b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 2949b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 2950b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 29511c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 29523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 29531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 29541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 29551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 295613aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 295720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 295820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29593b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 2960c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 296120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 296220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2963d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2964d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 2965d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 2966d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2967690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 2968690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 2969690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2970690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2971690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 29729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) || 29739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 2974690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2975690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 297629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 2977690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2978690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2979690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2980690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2981690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 298229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 2983690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2984690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2985690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2986690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2987690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2988690f546b0ee548dbfe997df36418e5302ec2d786James Dong 298925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangconst char *MPEG4Writer::Track::getTrackType() const { 299025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang return mIsAudio ? "Audio" : (mIsVideo ? "Video" : "Metadata"); 299125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang} 29928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 299325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 2994efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 300325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (mIsVideo) { 3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 300525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else { 300625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang writeNmhdBox(); 3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 3010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 3011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 3012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 3013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 3016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 3017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 3018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 3020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 3021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 302225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (mIsVideo) { 3023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 302425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else { 302525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang writeMetadataFourCCBox(); 3026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 3028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 302925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo) { 303025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang writeCttsBox(); 3031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 3036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 3037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 303925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeMetadataFourCCBox() { 304025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *mime; 304125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang bool success = mMeta->findCString(kKeyMIMEType, &mime); 304225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang CHECK(success); 304325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *fourcc = getFourCCForMime(mime); 304425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (fourcc == NULL) { 304525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("Unknown mime type '%s'.", mime); 304625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang TRESPASS(); 304725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } 304825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->beginBox(fourcc); // TextMetaDataSampleEntry 304925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeCString(mime); // metadata mime_format 305025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->endBox(); // mett 305125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang} 305225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang 3053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 3054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 30578b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 30588b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 305929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 306025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang TRESPASS(); 3061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 30638b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan mOwner->beginBox(fourcc); // video format 3064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 3067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 3070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 3071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 3074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 3075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 3076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 3079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 3080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 3081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 3082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 3084c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->writeInt8(0); // compressor string length 3085c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->write(" ", 31); 3086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 3087b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 3088b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3089b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 3090b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 3091b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 3092b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 3093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 3094b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 30959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 30969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim writeHvccBox(); 3097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3098b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3099b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 310058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar writeColrBox(); 3101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 3102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 310458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() { 310558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar ColorAspects aspects; 310658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar memset(&aspects, 0, sizeof(aspects)); 310758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar // TRICKY: using | instead of || because we want to execute all findInt32-s 310858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries) 310958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer) 311058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs) 311158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) { 311258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar int32_t primaries, transfer, coeffs; 311358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar bool fullRange; 311458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar ColorUtils::convertCodecColorAspectsToIsoAspects( 311558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar aspects, &primaries, &transfer, &coeffs, &fullRange); 311658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->beginBox("colr"); 311758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeFourcc("nclx"); 311858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(primaries); 311958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(transfer); 312058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(coeffs); 3121fffb0c8fbe16ac948619b85e1eea9e65a9daa0c9Pirama Arumuga Nainar mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0)); 312258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->endBox(); // colr 312358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar } 312458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar} 312558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar 3126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 3127b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 3128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 3129b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 31308b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 31318b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 313229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 313325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang TRESPASS(); 3134b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3135b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3136b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 3137b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3138b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 3140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 3143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 3144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 3145b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 3146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3147b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3149b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 3150b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 3151b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3152b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 3153b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 3154b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 3155b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 3156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 3157b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 3158b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3159b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3160b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3162b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 3163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 3164b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 316543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 3166b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3167b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 316843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(mCodecSpecificDataSize + 23, 128); 3169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3170b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3171b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 3172b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 3173b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 3174b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 3175b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3176b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3177b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 3178b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 3179b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 3180b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3181b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 318246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt8(0x00); // buffer size 24-bit (0x300) 318346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 318496bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t avgBitrate = 0; 318546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 318696bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t maxBitrate = 0; 318746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 318846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(maxBitrate); 318946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(avgBitrate); 3190b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3191b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3192b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 3193b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3194b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3195b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 3196b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 3197b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 3198b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 3199b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3200b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 3201b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3202b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 3203b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3204b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3205b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 3206b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 320743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 3208bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan 3209bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan // Make sure all sizes encode to a single byte. 3210bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan CHECK_LT(23 + mCodecSpecificDataSize, 128); 3211bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan 3212b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 3213b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3216b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 3217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 3218b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 3219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 3220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 3223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 3224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 3225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 322746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 0x01, 0x77, 0x00, // buffer size 96000 bytes 3228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 3230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 323196bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t avgBitrate = 0; 323246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 323396bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t maxBitrate = 0; 323446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 323546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(maxBitrate); 323646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(avgBitrate); 323746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 3238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 3241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3243b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 3244b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 3245b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 3246b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 3247b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3248b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 3249b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3250b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 3251b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3252b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3253efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 3254b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 3255b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 3256b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 3257b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 3258b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 3259b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 3260219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 3261b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 32628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 3263b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 3264b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 3265b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 3266b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 3267b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3268b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3269b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 3270b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 3271b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 3272b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3273b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3274b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 327520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 327625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (!mIsVideo) { 3277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 3278b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 3279b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 3280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 3281b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 3282b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 3283b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3284b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3285b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 3286b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 3287b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3288b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 3289b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3290b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3291b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 3292b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 3293b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 3294b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 3295b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 3296b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 3297b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 3298b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3299b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 3302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 3303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 3305b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3307b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 330925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeNmhdBox() { 331025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->beginBox("nmhd"); 331125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeInt32(0); // version=0, flags=0 331225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->endBox(); 331325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang} 331425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang 3315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 3316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 3317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3318b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 331925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeFourcc(mIsAudio ? "soun" : (mIsVideo ? "vide" : "meta")); // component subtype 3320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 332425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeCString(mIsAudio ? "SoundHandle": (mIsVideo ? "VideoHandle" : "MetadHandle")); 3325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3328efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 3329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 3330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 3331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 3333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 3334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 3335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 3336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 3337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 3338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 3339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 3340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 3341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 3342decc50efede28c5d73137c30d1a95d72dd405555David Yeh const char *lang = NULL; 3343decc50efede28c5d73137c30d1a95d72dd405555David Yeh int16_t langCode = 0; 3344decc50efede28c5d73137c30d1a95d72dd405555David Yeh if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) { 3345decc50efede28c5d73137c30d1a95d72dd405555David Yeh langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f); 3346decc50efede28c5d73137c30d1a95d72dd405555David Yeh } 3347decc50efede28c5d73137c30d1a95d72dd405555David Yeh mOwner->writeInt16(langCode); // language code 3348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 3353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 3354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 3355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 3356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 3358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 3359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 3360b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3363b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 3364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 3365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 3366b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 3367b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 3368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 3369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 3372b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 3373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 3375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 3376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 3377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 3380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 3381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 3382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 3383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 3386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 338743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mCodecSpecificDataSize, 5); 3388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 3390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 3391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 3392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 3393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 3394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 3396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 33989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 33999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() { 34009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim CHECK(mCodecSpecificData); 34019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim CHECK_GE(mCodecSpecificDataSize, 5); 34029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 34039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Patch avcc's lengthSize field to match the number 34049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // of bytes we use to indicate the size of a nal unit. 34059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim uint8_t *ptr = (uint8_t *)mCodecSpecificData; 34069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 34079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->beginBox("hvcC"); 34089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 34099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->endBox(); // hvcC 34109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 34119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 3412b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 3413b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 3414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 3415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 3417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 3418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 3419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 3422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 3423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 3424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 3425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 3426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 3427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3429000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 3430a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 3431b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 343343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 3434b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3435b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3436000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 3437000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 3438000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3439000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 3440000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 3441000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3442c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3443c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mSttsTableEntries->get(duration, 1)); 3444c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back to host byte order 3445c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 3446c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 3447b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 3448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 344920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3450965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 3451000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 3452000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 3453000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 3454000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 3455000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3456965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 3457c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 3458965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3459965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3460965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3461a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]", 3462c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 3463965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3464965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 3465000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3466c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t delta = mMinCttsOffsetTimeUs - getStartTimeOffsetScaledTime(); 3467c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) { 3468c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar // entries are <count, ctts> pairs; adjust only ctts 3469c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t duration = htonl(value[1]); // back to host byte order 3470c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar value[1] = htonl(duration - delta); 3471c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar }); 3472c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 3473965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 3474965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 3475965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3476b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 3477b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 3478b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3479c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 3480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 3481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 348225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 3483b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 3484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 3485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3486c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 3487c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 3488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 3489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 349020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 3492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 3493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3494c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 3495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 3496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 349720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 3499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 3500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3501c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 3502c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 3503c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 3504c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 3505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 350720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 350820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 350907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 351007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 351107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 351207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 351307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 351407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 3515e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() { 3516e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("hdlr"); 3517e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3518e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Predefined 3519e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3520e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[0] 3521e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[1] 3522e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[2] 3523e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt8(0); // Name (empty) 3524e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3525e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3526e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3527e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() { 3528e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3529e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3530e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("keys"); 3531e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3532e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(count); // Entry_count 3533e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3534e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3535e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3536e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t n = strlen(key); 3537e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(n + 8); 3538e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3539e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang write(key, n); // write without the \0 3540e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3541e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3542e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3543e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3544e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() { 3545e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3546e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3547e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("ilst"); 3548e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3549e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox(i + 1); // key id (1-based) 3550e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("data"); 3551e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3552e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3553e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang switch (type) { 35547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang case AMessage::kTypeString: 35557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang { 35567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang AString val; 35577c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang CHECK(mMetaKeys->findString(key, &val)); 35587c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(1); // type = UTF8 35597c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 35607c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang write(val.c_str(), strlen(val.c_str())); // write without \0 35617c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang break; 35627c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 35637c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 3564e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeFloat: 3565e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3566e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang float val; 3567e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findFloat(key, &val)); 35687c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(23); // type = float32 35697c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3570e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(*reinterpret_cast<int32_t *>(&val)); 3571e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3572e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3573e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3574e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeInt32: 3575e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3576e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang int32_t val; 3577e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findInt32(key, &val)); 35787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(67); // type = signed int32 35797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3580e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(val); 3581e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3582e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3583e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3584e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang default: 3585e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3586e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang ALOGW("Unsupported key type, writing 0 instead"); 35877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(77); // type = unsigned int32 35887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3589e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 3590e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3591e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3592e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3593e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // data 3594e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // key id 3595e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3596e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // ilst 3597e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3598e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3599e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() { 3600e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3601e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (count == 0) { 3602e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return; 3603e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3604e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3605e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("meta"); 3606e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeHdlr(); 3607e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeKeys(); 3608e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeIlst(); 3609e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3610e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3611e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 361207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 361307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 361407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 361507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 361607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 361707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 361807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 361907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 362007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 3621432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 3622432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 362307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 362407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 362507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 362607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 362707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 362807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 362907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 363007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 363120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3632