MPEG4Writer.cpp revision fe44e4f74fe2582cbf012687059278dbcbdaa6f7
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); 104fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang status_t stop(bool stopSource = true); 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; 121fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang void resetInternal(); 12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 124000e18370baae60ffd9f25b509501dd8c26deabfJames Dong enum { 125000e18370baae60ffd9f25b509501dd8c26deabfJames Dong kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 1268c460498c028888c533ab442be12b6d4b669b965James Dong kSampleArraySize = 1000, 127000e18370baae60ffd9f25b509501dd8c26deabfJames Dong }; 128000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // A helper class to handle faster write box with table entries 130c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar template<class TYPE, unsigned ENTRY_SIZE> 131c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar // ENTRY_SIZE: # of values in each entry 132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong struct ListTableEntries { 133c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar static_assert(ENTRY_SIZE > 0, "ENTRY_SIZE must be positive"); 134c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries(uint32_t elementCapacity) 135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mElementCapacity(elementCapacity), 136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTotalNumTableEntries(0), 137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry(0), 138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement(NULL) { 139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mElementCapacity, 0); 1402177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia // Ensure no integer overflow on allocation in add(). 141c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar CHECK_LT(ENTRY_SIZE, UINT32_MAX / mElementCapacity); 142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Free the allocated memory. 145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ~ListTableEntries() { 146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (!mTableEntryList.empty()) { 147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete[] (*it); 149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.erase(it); 150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Replace the value at the given position by the given value. 154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // There must be an existing value at the given position. 155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order 156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void set(const TYPE& value, uint32_t pos) { 158c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar CHECK_LT(pos, mTotalNumTableEntries * ENTRY_SIZE); 159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 161c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE)); 162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 169c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar (*it)[(pos % (mElementCapacity * ENTRY_SIZE))] = value; 170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Get the value at the given position by the given value. 173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value the retrieved value at the position in network byte order. 174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @return true if a value is found. 176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool get(TYPE& value, uint32_t pos) const { 177c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar if (pos >= mTotalNumTableEntries * ENTRY_SIZE) { 178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return false; 179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 182c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t iterations = (pos / (mElementCapacity * ENTRY_SIZE)); 183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 190c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar value = (*it)[(pos % (mElementCapacity * ENTRY_SIZE))]; 191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return true; 192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 194c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar // adjusts all values by |adjust(value)| 195c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar void adjustEntries( 196c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar std::function<void(size_t /* ix */, TYPE(& /* entry */)[ENTRY_SIZE])> update) { 197c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar size_t nEntries = mTotalNumTableEntries + mNumValuesInCurrEntry / ENTRY_SIZE; 198c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar size_t ix = 0; 199c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar for (TYPE *entryArray : mTableEntryList) { 200c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar size_t num = std::min(nEntries, (size_t)mElementCapacity); 201c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar for (size_t i = 0; i < num; ++i) { 202c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar update(ix++, (TYPE(&)[ENTRY_SIZE])(*entryArray)); 203c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar entryArray += ENTRY_SIZE; 204c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar } 205c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar nEntries -= num; 206c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar } 207c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar } 208c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar 209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Store a single value. 210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order. 211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void add(const TYPE& value) { 212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 214c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t nValues = mNumValuesInCurrEntry % ENTRY_SIZE; 215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries == 0 && nValues == 0) { 216c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCurrTableEntriesElement = new TYPE[ENTRY_SIZE * mElementCapacity]; 217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCurrTableEntriesElement != NULL); 218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.push_back(mCurrTableEntriesElement); 219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 221c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t pos = nEntries * ENTRY_SIZE + nValues; 222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement[pos] = value; 223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mNumValuesInCurrEntry; 225c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar if ((mNumValuesInCurrEntry % ENTRY_SIZE) == 0) { 226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mTotalNumTableEntries; 227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry = 0; 228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Write out the table entries: 232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 1. the number of entries goes first 233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 2. followed by the values in the table enties in order 234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg writer the writer to actual write to the storage 235c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void write(MPEG4Writer *writer) const { 236c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar CHECK_EQ(mNumValuesInCurrEntry % ENTRY_SIZE, 0); 237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries; 238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->writeInt32(nEntries); 239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong it != mTableEntryList.end(); ++it) { 241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(nEntries, 0); 242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries >= mElementCapacity) { 243c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, mElementCapacity); 244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong nEntries -= mElementCapacity; 245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 246c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar writer->write(*it, sizeof(TYPE) * ENTRY_SIZE, nEntries); 247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong break; 248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Return the number of entries in the table. 253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count() const { return mTotalNumTableEntries; } 254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong private: 256c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mElementCapacity; // # entries in an element 257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mTotalNumTableEntries; 258c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t mNumValuesInCurrEntry; // up to ENTRY_SIZE 259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong TYPE *mCurrTableEntriesElement; 260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mutable List<TYPE *> mTableEntryList; 261c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 262c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 263c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong }; 264c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 265c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 269b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen sp<IMediaSource> mSource; 27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 271a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 272a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 273eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 2741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 2759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bool mIsHevc; 2761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 27725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang bool mIsVideo; 2781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 279fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang bool mGotStartKeyFrame; 2809db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang bool mIsMalformed; 281bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 282c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 28343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 284826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar int64_t mLastDecodingTimeUs; 285e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 286d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 2871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 2888f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 292be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 29313aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 2941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 295c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool mSamplesHaveSameSize; 296c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 1> *mStszTableEntries; 297be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 298c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 1> *mStcoTableEntries; 299c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<off64_t, 1> *mCo64TableEntries; 300c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 3> *mStscTableEntries; 301c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 1> *mStssTableEntries; 302c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 2> *mSttsTableEntries; 303c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar ListTableEntries<uint32_t, 2> *mCttsTableEntries; 304965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 305000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMinCttsOffsetTimeUs; 306000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMaxCttsOffsetTimeUs; 307965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 3093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 3103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 3113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 3123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 3133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 3143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 3153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 3163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 3173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 3183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 3193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 3203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 3213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 324548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 32593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 3283c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 32970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 33070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 33193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 33293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 33325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 334872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 335872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 336872a481558350634a3fd5cb67939de288af00ecbJames Dong 337000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int32_t getStartTimeOffsetScaledTime() const; 338000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 34037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 3433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 3443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 3459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0); 3469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 350215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 3519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size); 3529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size); 3539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t parseHEVCCodecSpecificData( 3549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, HevcParameterSets ¶mSets); 3559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 356215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 357faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 35893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 35903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 36019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 36119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 362c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 363c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 364c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 365c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 366c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 367c059860c73678a202bfa33062723e8f82fb779d9James Dong 368690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 369690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 37013f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t mRotation; 371690f546b0ee548dbfe997df36418e5302ec2d786James Dong 3721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 3731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 3741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 37579761ab096f57c3027fad9556c2bc436672d614eJames Dong 37679761ab096f57c3027fad9556c2bc436672d614eJames Dong // Duration is time scale based 37779761ab096f57c3027fad9556c2bc436672d614eJames Dong void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 378965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 37945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 38045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong bool isTrackMalFormed() const; 38143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 3821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 389965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void writeCttsBox(); 390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 3939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim void writeHvccBox(); 394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 398efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeMdhdBox(uint32_t now); 399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 40125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang void writeNmhdBox(); 402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 403efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeTkhdBox(uint32_t now); 40458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar void writeColrBox(); 405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 40925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang void writeMetadataFourCCBox(); 410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 416fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu KuangMPEG4Writer::MPEG4Writer(int fd) { 417fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang initInternal(fd); 41830ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 41930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 42020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 4218bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong reset(); 42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 4241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 4261f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 4271f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 430fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 431fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mNextFd != -1) { 432fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang close(mNextFd); 433fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 434fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 435fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 436fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::initInternal(int fd) { 437fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGV("initInternal"); 438fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mFd = fd; 439fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mNextFd = -1; 440fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mInitCheck = mFd < 0? NO_INIT: OK; 441fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mIsRealTimeRecording = true; 442fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mUse4ByteNalLength = true; 443fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mUse32BitOffset = true; 444fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mIsFileSizeLimitExplicitlyRequested = false; 445fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mPaused = false; 446fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStarted = false; 447fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mWriterThreadStarted = false; 448fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSendNotify = false; 449fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mOffset = 0; 450fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMdatOffset = 0; 451fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMoovBoxBuffer = NULL; 452fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMoovBoxBufferOffset = 0; 453fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mWriteMoovBoxToMemory = false; 454fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mFreeBoxOffset = 0; 455fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStreamableFile = false; 456fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mEstimatedMoovBoxSize = 0; 457fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMoovExtraSize = 0; 458fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mInterleaveDurationUs = 1000000; 459fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mTimeScale = -1; 460fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStartTimestampUs = -1ll; 461fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLatitudex10000 = 0; 462fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLongitudex10000 = 0; 463fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mAreGeoTagsAvailable = false; 464fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStartTimeOffsetMs = -1; 465fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSwitchPending = false; 466fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMetaKeys = new AMessage(); 467fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang addDeviceMeta(); 468fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // Verify mFd is seekable 469fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang off64_t off = lseek64(mFd, 0, SEEK_SET); 470fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (off < 0) { 471fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGE("cannot seek mFd: %s (%d) %lld", strerror(errno), errno, (long long)mFd); 472fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang release(); 473fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 474fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang for (List<Track *>::iterator it = mTracks.begin(); 475fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang it != mTracks.end(); ++it) { 476fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang (*it)->resetInternal(); 477fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 480dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 481dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 482dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 483dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 484dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 485dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 486dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 487dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 488dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 489dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 490dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 491dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 492dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 493dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 494dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 495dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 496dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 497dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 49884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber int fd, const Vector<String16>& /* args */) const { 499dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 500dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 501dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 50225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang snprintf(buffer, SIZE, " %s track\n", getTrackType()); 503dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 504dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 505dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 506dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 507c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 50813210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 509377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); 51013210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 511dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 512dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 513dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 514dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 5158b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static 5168b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) { 5178b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (mime == NULL) { 5188b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 5198b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 5208b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strncasecmp(mime, "audio/", 6)) { 5218b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 5228b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "samr"; 5238b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 5248b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "sawb"; 5258b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 5268b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4a"; 5278b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 5288b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strncasecmp(mime, "video/", 6)) { 5298b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 5308b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4v"; 5318b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 5328b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "s263"; 5338b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 5348b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "avc1"; 5359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 5369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return "hvc1"; 5378b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 53825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (!strncasecmp(mime, "application/", 12)) { 53925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang return "mett"; 5408b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else { 54125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("Track (%s) other than video/audio/metadata is not supported", mime); 5428b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 5438b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 5448b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan} 5458b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan 546b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissenstatus_t MPEG4Writer::addSource(const sp<IMediaSource> &source) { 547bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 548bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 54929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Attempt to add source AFTER recording is started"); 550bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 551bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 552acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 553acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong CHECK(source.get() != NULL); 554acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 555acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong const char *mime; 556acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong source->getFormat()->findCString(kKeyMIMEType, &mime); 557acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 55825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (Track::getFourCCForMime(mime) == NULL) { 55925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("Unsupported mime '%s'", mime); 56025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang return ERROR_UNSUPPORTED; 56125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } 56225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang 56325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang // This is a metadata track or the first track of either audio or video 564acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // Go ahead to add the track. 565219f195159f93d627af2b243732e3f9020511a46James Dong Track *track = new Track(this, source, 1 + mTracks.size()); 56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 5672dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 5682dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 572acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.empty()) { 573acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("No source added"); 574acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return INVALID_OPERATION; 575acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 576acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 577a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 578a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 57993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 580a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 581a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 582a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 583a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 584a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 585a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 586a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 587a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 588a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 589a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 590a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 591a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 592a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 5937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() { 5947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // add device info and estimate space in 'moov' 5957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang char val[PROPERTY_VALUE_MAX]; 5967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size_t n; 5977c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // meta size is estimated by adding up the following: 5987c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - meta header structures, which occur only once (total 66 bytes) 5997c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - size for each key, which consists of a fixed header (32 bytes), 6007c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // plus key length and data length. 6017c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 66; 6027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.version.release", val, NULL) 6037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 6047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Version, val, n + 1); 6057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32; 6067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 6077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD 6087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.product.model", val, NULL) 6097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 6107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Model, val, n + 1); 6117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32; 6127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 6137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.display.id", val, NULL) 6147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 6157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Build, val, n + 1); 6167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32; 6177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 6187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif 6197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang} 6207c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 6212dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 6222dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 6232dec2b5be2056c6d9428897dc672185872d30d17James Dong // 6242dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 6252dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 6262dec2b5be2056c6d9428897dc672185872d30d17James Dong 62778a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 6282dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 62978a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 6302dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 6312dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 6322dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 6332dec2b5be2056c6d9428897dc672185872d30d17James Dong 6342dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 6352dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 6362dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 63778a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 6382dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 6392dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 6402dec2b5be2056c6d9428897dc672185872d30d17James Dong 64178a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 642a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 64378a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 64478a1a286f736888ae7af8860b2c424af0d978848James Dong } 64578a1a286f736888ae7af8860b2c424af0d978848James Dong 64678a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 64778a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 64878a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 64978a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 6500ca31521644b9396829850f7400d23f9b107cc64Johan Redestig ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000; 65178a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 65278a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 65378a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 65478a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 65578a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 65678a1a286f736888ae7af8860b2c424af0d978848James Dong } 65778a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 65878a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 65978a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 66078a1a286f736888ae7af8860b2c424af0d978848James Dong } 6612dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6622dec2b5be2056c6d9428897dc672185872d30d17James Dong } 66378a1a286f736888ae7af8860b2c424af0d978848James Dong 6642dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 6652dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 6662dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6672dec2b5be2056c6d9428897dc672185872d30d17James Dong 6682dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 6692dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 6702dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 6712dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 6722dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6732dec2b5be2056c6d9428897dc672185872d30d17James Dong 6747c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // Account for the extra stuff (Geo, meta keys, etc.) 6757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size += mMoovExtraSize; 6767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 677a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the" 678a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn " estimated moov size %" PRId64 " bytes", 6792dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 6802dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 6812dec2b5be2056c6d9428897dc672185872d30d17James Dong} 6822dec2b5be2056c6d9428897dc672185872d30d17James Dong 6832dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 684674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 68525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 687fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStartMeta = param; 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 945fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::finishCurrentSession() { 946fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang reset(false /* stopSource */); 947fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 948fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 949fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::switchFd() { 950fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGV("switchFd"); 951fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang Mutex::Autolock l(mLock); 952fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mSwitchPending) { 953fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return OK; 954fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 955fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 956fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mNextFd == -1) { 957fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGW("No FileDescripter for next recording"); 958fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return INVALID_OPERATION; 959fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 960fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 961fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSwitchPending = true; 962fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang sp<AMessage> msg = new AMessage(kWhatSwitch, mReflector); 963fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang status_t err = msg->post(); 964fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 965fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return err; 966fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 967fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 968fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::reset(bool stopSource) { 969674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 97037187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 971411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 972411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 973411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 974411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 975411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 976411ba422e3635d534928ffd81abf54f4f291c739James Dong } 977411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 978411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 979411ba422e3635d534928ffd81abf54f4f291c739James Dong } 98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 98237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 9838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 98465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 987fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang status_t status = (*it)->stop(stopSource); 98837187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 98937187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 99037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 99120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 9938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 9948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 99665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 99765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 99865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 99965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 100065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 100165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 1002a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us", 100365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 100420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 100520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 10077837c17063a4c50bc856ba59418516fdab731de7James Dong 100837187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 100937187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 1010411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 101137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 101237187916a486504acaf83bea30147eb5fbf46ae5James Dong } 101337187916a486504acaf83bea30147eb5fbf46ae5James Dong 101420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 10151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 1016c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 10171f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); 1018c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 10191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 1020c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 10211f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint64_t size = mOffset - mMdatOffset; 10221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 1023c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 10241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 1025c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10277b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Construct moov box now 10287837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 10297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = mStreamableFile; 10307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 10317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // There is no need to allocate in-memory cache 10327b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // for moov box if the file is not streamable. 10337b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 10347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 10357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong CHECK(mMoovBoxBuffer != NULL); 10367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 1037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 103820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // mWriteMoovBoxToMemory could be set to false in 10407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // MPEG4Writer::write() method 10417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 10427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 10437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Content of the moov box is saved in the cache, and the in-memory 10447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // moov box needs to be written to the file in a single shot. 10457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 104643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 10477837c17063a4c50bc856ba59418516fdab731de7James Dong 10487837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 1049c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 10507837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 1051674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 10527837c17063a4c50bc856ba59418516fdab731de7James Dong 10537837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 1054c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 10557837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 10567837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 10577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } else { 10587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ALOGI("The mp4 file will not be streamable."); 10597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 10607837c17063a4c50bc856ba59418516fdab731de7James Dong 10617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Free in-memory cache for moov box 10627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mMoovBoxBuffer != NULL) { 10637837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 10647837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 10657837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 10667837c17063a4c50bc856ba59418516fdab731de7James Dong } 10677837c17063a4c50bc856ba59418516fdab731de7James Dong 10680c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 106920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1070411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 107137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 107220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 107320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1074efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() { 1075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 1076efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 1077efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // while time function returns Unix epoch values which starts 1078efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // at 1970-01-01. Lets add the number of seconds between them 10792b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60); 10802b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen if (now < 0 || uint32_t(now) > UINT32_MAX - delta) { 10812b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen return 0; 10822b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen } 10832b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen uint32_t mpeg4Time = uint32_t(now) + delta; 1084efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson return mpeg4Time; 1085efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson} 1086efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson 1087efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 1088efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 1089b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 1090b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 1091b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 1092b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 1093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 1094b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 1095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 1096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 1097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 1098b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 1099b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1100b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 1102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1104b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1105b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1106b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 1109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 1110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1111b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1112b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 1113b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 1114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 111507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 111607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 111707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 1118e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeMetaBox(); 1119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 1120b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 1121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 1122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 1123b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1124b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 1125b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 11272cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 1128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 1129b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1130b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 1131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 1132b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 1133b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 11348284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 11358284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("isom"); 11368284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("3gp4"); 1137b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 11388284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 11398284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 1140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 11418284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 1142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 1145b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 114707ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 114807ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 114907ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 115007ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 115107ec01904613a0bac32caaa8444b4690998faed7James Dong 115207ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 115307ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 115496626b7f9a4e5c9e1e04f7f710383631d1470364Marco Nelissen if (property_get_bool("rw.media.record.test", false)) { 115507ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 115607ec01904613a0bac32caaa8444b4690998faed7James Dong } 115707ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 115807ec01904613a0bac32caaa8444b4690998faed7James Dong} 115907ec01904613a0bac32caaa8444b4690998faed7James Dong 116070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 116107ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 116207ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 116307ec01904613a0bac32caaa8444b4690998faed7James Dong return; 116407ec01904613a0bac32caaa8444b4690998faed7James Dong } 116507ec01904613a0bac32caaa8444b4690998faed7James Dong 116670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 116770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 116870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 116970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 117070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 117170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 117270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 117370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 117470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 117513aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 117613aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 117713aec890216948b0c364f8f92792129d0335f506James Dong return OK; 117813aec890216948b0c364f8f92792129d0335f506James Dong} 117913aec890216948b0c364f8f92792129d0335f506James Dong 118013aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 118113aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 118213aec890216948b0c364f8f92792129d0335f506James Dong} 118313aec890216948b0c364f8f92792129d0335f506James Dong 118413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 118513aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 118613aec890216948b0c364f8f92792129d0335f506James Dong} 118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1188c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 1189c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1191c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1192c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1193c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 120103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 120203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 120303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 120403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 120503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 120603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 120703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 120803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 120903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 121003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 121103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 121203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 121303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 121480f78b773f92048944a850efb7b60629643370cdPraveen Chavanoff64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) { 121580f78b773f92048944a850efb7b60629643370cdPraveen Chavan off64_t old_offset = mOffset; 121680f78b773f92048944a850efb7b60629643370cdPraveen Chavan 121780f78b773f92048944a850efb7b60629643370cdPraveen Chavan const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs 121880f78b773f92048944a850efb7b60629643370cdPraveen Chavan 121980f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset(); 122080f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *currentNalStart = dataStart; 122180f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *nextNalStart; 122280f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *data = dataStart; 122380f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t nextNalSize; 122480f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ? 122580f78b773f92048944a850efb7b60629643370cdPraveen Chavan kExtensionNALSearchRange : buffer->range_length(); 122680f78b773f92048944a850efb7b60629643370cdPraveen Chavan 122780f78b773f92048944a850efb7b60629643370cdPraveen Chavan while (getNextNALUnit(&data, &searchSize, &nextNalStart, 122880f78b773f92048944a850efb7b60629643370cdPraveen Chavan &nextNalSize, true) == OK) { 122910cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */; 123080f78b773f92048944a850efb7b60629643370cdPraveen Chavan MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize); 123180f78b773f92048944a850efb7b60629643370cdPraveen Chavan addLengthPrefixedSample_l(nalBuf); 123280f78b773f92048944a850efb7b60629643370cdPraveen Chavan nalBuf->release(); 123380f78b773f92048944a850efb7b60629643370cdPraveen Chavan 123480f78b773f92048944a850efb7b60629643370cdPraveen Chavan currentNalStart = nextNalStart; 123580f78b773f92048944a850efb7b60629643370cdPraveen Chavan } 123680f78b773f92048944a850efb7b60629643370cdPraveen Chavan 123780f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t currentNalOffset = currentNalStart - dataStart; 123880f78b773f92048944a850efb7b60629643370cdPraveen Chavan buffer->set_range(buffer->range_offset() + currentNalOffset, 123980f78b773f92048944a850efb7b60629643370cdPraveen Chavan buffer->range_length() - currentNalOffset); 124080f78b773f92048944a850efb7b60629643370cdPraveen Chavan addLengthPrefixedSample_l(buffer); 124180f78b773f92048944a850efb7b60629643370cdPraveen Chavan 124280f78b773f92048944a850efb7b60629643370cdPraveen Chavan return old_offset; 124380f78b773f92048944a850efb7b60629643370cdPraveen Chavan} 124480f78b773f92048944a850efb7b60629643370cdPraveen Chavan 1245c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 1246c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 124730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 124830ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 124903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1250b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 1251b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 1252c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1253b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 1254c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1255b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 1256c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1257b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1258c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1259c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 1260c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1261c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1262c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 1263b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1264b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 1265b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 126643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(length, 65536); 126730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1268b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 1269c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1270b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1271c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1272c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1273b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 1274b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 127530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 127630ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 127730ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 127830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 12797837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 1280674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 12817837c17063a4c50bc856ba59418516fdab731de7James Dong 12827837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 12837837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 12847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 1285c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 12861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 12877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // The reserved moov box at the beginning of the file 12887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // is not big enough. Moov box should be written to 12897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the end of the file from now on, but not to the 12907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // in-memory cache. 12917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 12927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // We write partial moov box that is in the memory to 12937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the file first. 1294c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 12957837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 12967837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 12977837c17063a4c50bc856ba59418516fdab731de7James Dong } 1298674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 1299674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 13007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ::write(mFd, ptr, bytes); 13017837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 13027b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 13037b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // All subsequent moov box content will be written 13047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // to the end of the file. 13057837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 13067837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 13077837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 13087837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 13097837c17063a4c50bc856ba59418516fdab731de7James Dong } 13107837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1311674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 13127837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 13137837c17063a4c50bc856ba59418516fdab731de7James Dong } 13147837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 13157837c17063a4c50bc856ba59418516fdab731de7James Dong} 13167837c17063a4c50bc856ba59418516fdab731de7James Dong 1317e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) { 1318e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mBoxes.push_back(mWriteMoovBoxToMemory? 1319e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mMoovBoxBufferOffset: mOffset); 1320e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 1321e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 1322e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(id); 1323e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1324e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 13260c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13287837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 13297837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 13360c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1338c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13417837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 13427837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 13437837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 13447837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1345c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 13467837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 13477837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1348c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 13497837c17063a4c50bc856ba59418516fdab731de7James Dong } 135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1353674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1358674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1363674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1368674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1373674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 137520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 13770c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 1378674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 138107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 138207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 138307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 138407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 138507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 138607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 138707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 138807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 138907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 139007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 139107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 139207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 139307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 139407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 139507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 139607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 139707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 139807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 139907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 140007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 140107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 140207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 140307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 140407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 140507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 140607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 140707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 140807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 140907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 141007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 141107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 141207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 141307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 141407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 141507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 141607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 141707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 141807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 141907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 142007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 142107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 142207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 142307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 142407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 142507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 142607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 142707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 142807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 142907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 143007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 143107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 143207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 143307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 143407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 143507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 143607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 143707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 143807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 143907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 144007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 144107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 144207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 144307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 144407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 144507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 144607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 144707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 144807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 14497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 30; 145007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 145107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 145207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 1453e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) { 1454e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (captureFps <= 0.0f) { 1455e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return BAD_VALUE; 1456e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 1457e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 14587c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps); 14597c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32; 14607c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 1461e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return OK; 1462e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1463e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 14644dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) { 14654dbff11975e737482537e1636051690188f3fbc4Praveen Chavan if (layerCount > 9) { 14664dbff11975e737482537e1636051690188f3fbc4Praveen Chavan return BAD_VALUE; 14674dbff11975e737482537e1636051690188f3fbc4Praveen Chavan } 14684dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 14694dbff11975e737482537e1636051690188f3fbc4Praveen Chavan if (layerCount > 0) { 14704dbff11975e737482537e1636051690188f3fbc4Praveen Chavan mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount); 14714dbff11975e737482537e1636051690188f3fbc4Praveen Chavan mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32; 14724dbff11975e737482537e1636051690188f3fbc4Praveen Chavan } 14734dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 14744dbff11975e737482537e1636051690188f3fbc4Praveen Chavan return OK; 14754dbff11975e737482537e1636051690188f3fbc4Praveen Chavan} 14764dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 1477fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::notifyApproachingLimit() { 1478fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang Mutex::Autolock autolock(mLock); 1479fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // Only notify once. 1480fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mSendNotify) { 1481fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return; 1482fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1483fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGW("Recorded file size is approaching limit %" PRId64 "bytes", 1484fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mMaxFileSizeLimitBytes); 1485fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING, 0); 1486fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSendNotify = true; 1487fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1488fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1490674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 149378a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 149478a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 149578a1a286f736888ae7af8860b2c424af0d978848James Dong} 149678a1a286f736888ae7af8860b2c424af0d978848James Dong 1497d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1498d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1499d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1500d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1501d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1502956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1503d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1504d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1505d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1506d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 15071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 150877e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 150977e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 151077e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 151177e8ae9967a078770416619e99ddb5b010def312James Dong } 1512fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1513acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1514acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1515acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1516acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1517d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1518d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1519fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangbool MPEG4Writer::approachingFileSizeLimit() { 1520fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // No limit 1521fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mMaxFileSizeLimitBytes == 0) { 1522fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return false; 1523fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1524fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1525fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1526fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang for (List<Track *>::iterator it = mTracks.begin(); 1527fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang it != mTracks.end(); ++it) { 1528fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1529fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1530fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1531fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (!mStreamableFile) { 1532fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // Add 1024 bytes as error tolerance 1533fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return nTotalBytesEstimate + 1024 >= (90 * mMaxFileSizeLimitBytes) / 100; 1534fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1535fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1536fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return (nTotalBytesEstimate >= (90 * mMaxFileSizeLimitBytes) / 100); 1537fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1538fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1539d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1540d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1541d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1542d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1543d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1544d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1545d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1546d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1547d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1548d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1549d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1550d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1551d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1552d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1553d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 155425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 155525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 155625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 155725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 155825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 155925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 156025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 156125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 156225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 156325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 156425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 156525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 156625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1567f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1568a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("setStartTimestampUs: %" PRId64, timeUs); 156943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 15703c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1571065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1572f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1573a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs); 15743c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 15753c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 15763c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1577f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 15783c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 15793c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 15803c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 15813c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 158258ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 158358ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 158458ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 158558ae9c530247668f8af36e30d228c716c226b3d4James Dong} 158658ae9c530247668f8af36e30d228c716c226b3d4James Dong 158720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 158920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1590b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId) 159120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 159225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 159320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 159420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1595a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1596a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1597eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1598fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mGotStartKeyFrame(false), 15999db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed(false), 1600bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1601c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1602956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1603be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1604c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1605c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1606c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)), 1607c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)), 1608c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)), 1609c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)), 1610c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)), 161120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 161225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1613548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 161413f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 161513f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 161619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 16178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 16181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 16191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 16201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 16219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC); 16221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 162325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mIsVideo = !strncasecmp(mime, "video/", 6); 16241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 16251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 16261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1627b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar // store temporal layer count 162825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo) { 1629b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar int32_t count; 1630b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar if (mMeta->findInt32(kKeyTemporalLayerCount, &count) && count > 1) { 1631b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar mOwner->setTemporalLayerCount(count); 1632b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar } 1633b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar } 1634b1803b01ed332aa2ed05536c4486078e9d02760aLajos Molnar 1635c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1636c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1637c059860c73678a202bfa33062723e8f82fb779d9James Dong 1638fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang// Clear all the internal states except the CSD data. 1639fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::Track::resetInternal() { 1640fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mDone = false; 1641fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mPaused = false; 1642fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mResumed = false; 1643fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStarted = false; 1644fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mGotStartKeyFrame = false; 1645fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mIsMalformed = false; 1646fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mTrackDurationUs = 0; 1647fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mEstimatedTrackSizeBytes = 0; 1648fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSamplesHaveSameSize = 0; 1649fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mStszTableEntries != NULL) { 1650fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mStszTableEntries; 1651fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000); 1652fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1653fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1654fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mStcoTableEntries != NULL) { 1655fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mStcoTableEntries; 1656fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000); 1657fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1658fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mCo64TableEntries != NULL) { 1659fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mCo64TableEntries; 1660fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000); 1661fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1662fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1663fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mStscTableEntries != NULL) { 1664fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mStscTableEntries; 1665fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStscTableEntries = new ListTableEntries<uint32_t, 3>(1000); 1666fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1667fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mStssTableEntries != NULL) { 1668fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mStssTableEntries; 1669fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mStssTableEntries = new ListTableEntries<uint32_t, 1>(1000); 1670fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1671fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mSttsTableEntries != NULL) { 1672fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mSttsTableEntries; 1673fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSttsTableEntries = new ListTableEntries<uint32_t, 2>(1000); 1674fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1675fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mCttsTableEntries != NULL) { 1676fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang delete mCttsTableEntries; 1677fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mCttsTableEntries = new ListTableEntries<uint32_t, 2>(1000); 1678fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1679fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mReachedEOS = false; 1680fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1681fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 16821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 16831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1684c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1685c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 1686c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 1687c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1688c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 16891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 169078a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 169178a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 169278a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 169378a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1694c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1695c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1696c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1697c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 169878a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 169978a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 170078a1a286f736888ae7af8860b2c424af0d978848James Dong } 17011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 17021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 17031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 17041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 17051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1706c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(chunkId)); 1707c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(sampleId)); 1708c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(1)); 17091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 17101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 17111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1712c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 17131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 17141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 17151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 171679761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 17171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 17185a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 1719377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGW("0-duration samples found: %zu", sampleCount); 17205a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1721c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1722c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 17231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 17241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1725965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1726965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1727965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 172825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (!mIsVideo) { 1729965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1730965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1731c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1732c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1733965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1734965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1735fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::setNextFd(int fd) { 1736fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGV("addNextFd"); 1737fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang Mutex::Autolock l(mLock); 1738fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mLooper == NULL) { 1739fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mReflector = new AHandlerReflector<MPEG4Writer>(this); 1740fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLooper = new ALooper; 1741fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLooper->registerHandler(mReflector); 1742fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLooper->start(); 1743fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1744fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1745fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mNextFd != -1) { 1746fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // No need to set a new FD yet. 1747fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return INVALID_OPERATION; 1748fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1749fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mNextFd = fd; 1750fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang return OK; 1751fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1752fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 1753c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1754c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1755c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1756c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1757c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1758c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1759c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 17601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 17611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1762c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 17633856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 1764c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1765c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1766c059860c73678a202bfa33062723e8f82fb779d9James Dong 1767c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1768c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1769c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1770c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1771c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1772c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1773c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1774c059860c73678a202bfa33062723e8f82fb779d9James Dong 1775c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1776c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1777c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1778c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1779c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1780c059860c73678a202bfa33062723e8f82fb779d9James Dong 178143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 178219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 178319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 1784fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangvoid MPEG4Writer::onMessageReceived(const sp<AMessage> &msg) { 1785fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang switch (msg->what()) { 1786fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang case kWhatSwitch: 1787fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang { 1788fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang finishCurrentSession(); 1789fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLock.lock(); 1790fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang int fd = mNextFd; 1791fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mNextFd = -1; 1792fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mLock.unlock(); 1793fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang initInternal(fd); 1794fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang start(mStartMeta.get()); 1795fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSwitchPending = false; 1796fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED, 0); 1797fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang break; 1798fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1799fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang default: 1800fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang TRESPASS(); 1801fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 1802fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang} 1803fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 180419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 180519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 1806fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 180719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 180819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 18099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim uint32_t type; 18109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const void *data = NULL; 18119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t size = 0; 181219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 18139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mMeta->findData(kKeyAVCC, &type, &data, &size); 18149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) { 18159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mMeta->findData(kKeyHVCC, &type, &data, &size); 181619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 181719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 181819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 181919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 18209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (esds.getCodecSpecificInfo(&data, &size) != OK) { 18219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim data = NULL; 18229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size = 0; 182319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 182419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 182519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 18269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) { 18279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mGotAllCodecSpecificData = true; 18289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 182920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 183020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 183120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 183220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 183320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1834c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 1835c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 1836c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 1837c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 1838c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 1839c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 1840c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 1841c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 1842c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 1843c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 1844c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 1845c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 1846c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 1847c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 1848c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 1849c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 185120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 185220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 185320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 185420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 185520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 185693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 18573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 185893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 185993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 186093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 186193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 186293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 186393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 1864a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs); 186593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 186693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 186793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 186893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 186993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 187093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 18711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 18721c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 18733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 18741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 18751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 18761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 18771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 18781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18791c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 18803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 18811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 18821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 18831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 18851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 18861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 18881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 18891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 18901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 18911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 18921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 18931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 189443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 18951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 18961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1897fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1898a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("writeChunkToFile: %" PRId64 " from %s track", 189925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang chunk->mTimeStampUs, chunk->mTrack->getTrackType()); 1900fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1901fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1902fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1903fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1904fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 19059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc()) 190680f78b773f92048944a850efb7b60629643370cdPraveen Chavan ? addMultipleLengthPrefixedSamples_l(*it) 1907fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1908fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1909fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1910fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1911fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 19121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 19151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1916fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 19171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1918fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 19191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 19201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1921fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 19223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 19231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 192470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 192570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1926e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 192770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 19281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 192970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 193070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 193170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 19321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 1933377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGD("%zu chunks are written in the last batch", outstandingChunks); 19341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 19351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1936fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 19373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 19381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 19401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 19411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 19421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 19431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 19441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 19451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 19461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 19471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 19481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 19533856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 1954fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 19551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 19581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 19591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1960fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 19611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 19621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 19631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1964fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1965fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1966fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 196770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 196870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 196970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 197070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 197170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 197270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 197370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1974fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 19751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1977fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1978fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 19791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 19801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19811c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 19823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 19831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1984a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1985fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1986fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 19871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1988fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1989fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1990fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1991fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 19921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 19931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 19941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1995de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // In real time recording mode, write without holding the lock in order 1996de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // to reduce the blocking time for media track threads. 1997de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // Otherwise, hold the lock until the existing chunks get written to the 1998de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // file. 1999fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 2000de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 2001de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.unlock(); 2002de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2003fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 2004de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 2005de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.lock(); 2006de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2007fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 20081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 2009fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 2010fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 20111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 20121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 20131c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 20143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 20151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 20161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 20171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 2018e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 20191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 20201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 20211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 20221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 202370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 202470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 20251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 20261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 20271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 20281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 20291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 20301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 20311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 20321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 2033411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 20341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 20351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 20361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 20371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 203893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 2039a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 2040a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 2041a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 2042a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 2043a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 204425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 204593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 204619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 204719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 204819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 204970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 205019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 205113f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 205225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 205313f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 205413f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 205513f6284305e4b27395a23db7882d670bdb1bcae1James Dong 205693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 205793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2058f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 2059de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 2060a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 2061a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 2062a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 2063a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 2064a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 2065a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 206686b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 206786b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 2068a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 206986b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 207086b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 207186b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 207286b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 207386b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 2074a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs); 2075a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2076a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2077f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 2078a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2079f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 208025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 208125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 208225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 208325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 208420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 208520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 208620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 208720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 208820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 208920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 2090eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 2091c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 209225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 2093956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 20941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 209543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 2096826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar mLastDecodingTimeUs = -1; 209720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 209825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 209920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 210025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 210125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 210220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 210320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 210437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 2105a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 210637187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 2107a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 2108a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2109fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuangstatus_t MPEG4Writer::Track::stop(bool stopSource) { 2110fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("%s track stopping. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop"); 2111eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 211229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 2113eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 2114eaae38445a340c4857c1c5569475879a728e63b7James Dong } 2115eaae38445a340c4857c1c5569475879a728e63b7James Dong 211620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 211737187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 211820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 211920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 2120fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (stopSource) { 2121fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("%s track source stopping", getTrackType()); 2122fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSource->stop(); 2123fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("%s track source stopped", getTrackType()); 2124fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 212572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 212620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 212720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 2128377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 212937187916a486504acaf83bea30147eb5fbf46ae5James Dong 2130fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("%s track stopped. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop"); 213137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 213220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 213320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 213425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 213525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 213625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 213725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 213820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 213920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 214020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 214120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 214237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 2143377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT return (void *)(uintptr_t)err; 214420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 214520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 21473856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 21483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 21503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 21513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 21523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 21543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 21553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21563856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 21573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 21583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 21593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 216047d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar const uint8_t *nextStartCode = findNextNalStartCode(data, length); 21613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 21623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 216329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 21643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 21653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 21683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 21693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 217029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 21713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 21723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 21743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 21753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 21763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 21773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 21783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 21793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 21803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 218107b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar // COULD DO: set profile/level to the lowest required to support all SPSs 218229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 21833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 21843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 21873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 21883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 21893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 21913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 21923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 21943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 21953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 21963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 21983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 21999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyCodecSpecificData(data, size, 4 + 7); 22009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 22019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData( 22039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size) { 22049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGV("copyHEVCCodecSpecificData"); 22059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2) 22079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyCodecSpecificData(data, size, 23); 22089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 22099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData( 22119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, size_t minLength) { 22129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (size < minLength) { 2213377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 22143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 22189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 22199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 22209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 22219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = size; 22233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 22243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 22253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 22263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 22283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 22293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 22313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 22323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 22333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 22343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 22353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 22363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 22373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 22383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 22393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 22403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 22413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 22423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 22433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 22443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 22453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 224629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 22473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 22503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 22513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 22533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 22543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 225529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 22563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 22593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 22603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 22623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 226329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 22643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 22683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 22723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 22733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 22743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 22753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 22783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 22793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 22803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 228129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 22823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 2286377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 22873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 22923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 22933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 22943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 229529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 22963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 22973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 2299377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 23003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 23013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23031374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 23041374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 23051374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 23061374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 23073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 23083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 23093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 23103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 23113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 231229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 23133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 23143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23161374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 23173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 23183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 2319548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 232003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 232103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 2322548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 232303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 232429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 232503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 232603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 232703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 2329377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 233003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 233103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 233203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 23343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 23353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 233603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 233703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 233903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 234003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 234103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 23433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 234403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 23459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 23469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = 0; 23479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 23489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 23499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 235003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 23513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 23523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 23533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 23543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 235503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2357b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2358b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 2359b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2360b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 2361b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 236203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 23643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 23653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 23663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 23673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 23683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 23693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 23703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 23713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 23723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 23733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 23743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 23753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 23763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 23773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 23783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 23793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 23803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 23813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 23823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 23833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 23843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 23853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 23863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 23873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 23883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 23893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 23903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 23913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 23923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 23933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 239403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 239503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 239603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 239703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 23999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData( 24009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, HevcParameterSets ¶mSets) { 24019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGV("parseHEVCCodecSpecificData"); 24039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *tmp = data; 24049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *nextStartCode = data; 24059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t bytesLeft = size; 24069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 240747d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4); 24089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4); 24099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (err != OK) { 24109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 24119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Move on to find the next parameter set 24149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bytesLeft -= nextStartCode - tmp; 24159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim tmp = nextStartCode; 24169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t csdSize = 23; 24199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const size_t numNalUnits = paramSets.getNumNalUnits(); 24209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) { 24219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim int type = kMandatoryHevcNalUnitTypes[i]; 24229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 24239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (numParamSets == 0) { 24249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Cound not find NAL unit of type %d", type); 24259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 24269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) { 24299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim int type = kHevcNalUnitTypes[i]; 24309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 24319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (numParamSets > 0xffff) { 24329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Too many seq parameter sets (%zu) found", numParamSets); 24339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 24349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim csdSize += 3; 24369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t j = 0; j < numNalUnits; ++j) { 24379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (paramSets.getType(j) != type) { 24389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim continue; 24399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim csdSize += 2 + paramSets.getSize(j); 24419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = csdSize; 24449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return OK; 24459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 24469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData( 24489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size) { 24499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData != NULL) { 24519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Already have codec specific data"); 24529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 24539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (size < 4) { 24569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Codec specific data length too short: %zu", size); 24579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 24589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Data is in the form of HEVCCodecSpecificData 24619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (memcmp("\x00\x00\x00\x01", data, 4)) { 24629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyHEVCCodecSpecificData(data, size); 24639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim HevcParameterSets paramSets; 24669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) { 24673d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim ALOGE("failed parsing codec specific data"); 24689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 24699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificData = malloc(mCodecSpecificDataSize); 24729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 24739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = 0; 24749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 24759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 24769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData, 24783d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2); 24799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (err != OK) { 24803d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim ALOGE("failed constructing HVCC atom"); 24819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return err; 24829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 24839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 24849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return OK; 24859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 24869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 2487872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 2488872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 2489872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 2490872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 2491872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 2492872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2493872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 2494872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 2495872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2496872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 2497872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2498872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2499872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2500872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 2501872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2502872a481558350634a3fd5cb67939de288af00ecbJames Dong} 2503872a481558350634a3fd5cb67939de288af00ecbJames Dong 250437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 250530ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 250613aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 250743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 250813aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 250913aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 25107c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar int32_t nActualFrames = 0; // frames containing non-CSD data (non-0 length) 251113aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 2512965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 2513965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 2514965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 2515965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 2516965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 2517000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 2518a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 2519965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 2520000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 2521000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2522000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 252343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2524c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 2525e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2526a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 2527a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 252825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (mIsVideo) { 2529a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 253025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else { 253125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0); 2532a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 2533de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2534de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2535de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2536de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2537985f838934510983d8a887461e98dca60a6e858fJames Dong 2538d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 253920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 254093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 254120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 254225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *trackName = getTrackType(); 254393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 254420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 254520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 254620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 254713aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 254820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 254920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 255020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2551a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 2552a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 2553a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2554a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2555a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2556a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2557a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2558a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2559a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 256030ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 256130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 256203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 256303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 256403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 25657c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // if config format (at track addition) already had CSD, keep that 25667c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // UNLESS we have not received any frames yet. 25677c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // TODO: for now the entire CSD has to come in one frame for encoders, even though 25687c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // they need to be spread out for decoders. 25697c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar if (mGotAllCodecSpecificData && nActualFrames > 0) { 25707c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar ALOGI("ignoring additional CSD for video track after first frame"); 25717c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else { 25727c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar mMeta = mSource->getFormat(); // get output format after format change 25737c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar 25747c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar if (mIsAvc) { 25757c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar status_t err = makeAVCCodecSpecificData( 25767c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar (const uint8_t *)buffer->data() 25777c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar + buffer->range_offset(), 25787c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 25797c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar CHECK_EQ((status_t)OK, err); 25807c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else if (mIsHevc) { 25817c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar status_t err = makeHEVCCodecSpecificData( 25827c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar (const uint8_t *)buffer->data() 25837c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar + buffer->range_offset(), 25847c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 25857c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar CHECK_EQ((status_t)OK, err); 25867c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else if (mIsMPEG4) { 25877c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(), 25887c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 25897c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } 259030ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 259130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 259230ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 259330ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 259430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2595548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 259630ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2597a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2598a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2599e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang // Per-frame metadata sample's size must be smaller than max allowed. 2600e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang if (!mIsVideo && !mIsAudio && buffer->range_length() >= kMaxMetadataSize) { 2601e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang ALOGW("Buffer size is %zu. Maximum metadata buffer size is %lld for %s track", 2602e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang buffer->range_length(), (long long)kMaxMetadataSize, trackName); 2603e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang buffer->release(); 2604e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang mSource->stop(); 2605e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang mIsMalformed = true; 2606e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang break; 2607e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang } 2608e1b943f21dff25044b349d4d628d9adb0c2e0b74Hangyu Kuang 26097c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar ++nActualFrames; 26107c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar 2611d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2612d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2613d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2614d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2615d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2616d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2617d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2618d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2619d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2620d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 26219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mIsAvc || mIsHevc) StripStartcode(copy); 2622e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2623b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 26249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mIsAvc || mIsHevc) { 2625b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2626b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2627b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2628b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2629b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2630b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2631050b28a593350047845a45a14cc5026221ac1620James Dong 2632d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 26331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 26341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 26351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2636d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2637fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mOwner->switchFd() != OK) { 2638fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGW("Recorded file size exceeds limit %" PRId64 "bytes", 2639fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mOwner->mMaxFileSizeLimitBytes); 2640fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mSource->stop(); 2641fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mOwner->notify( 2642fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2643fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } else { 2644fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGV("%s Current recorded file size exceeds limit %" PRId64 "bytes. Switching output", 2645fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang getTrackType(), mOwner->mMaxFileSizeLimitBytes); 2646fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2647d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang copy->release(); 2648d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2649d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2650fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang 2651d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2652316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds", 2653316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang mOwner->mMaxFileDurationLimitUs); 2654d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2655d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang copy->release(); 2656d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 2657d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2658d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2659d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2660fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mOwner->approachingFileSizeLimit()) { 2661fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mOwner->notifyApproachingLimit(); 2662fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2663050b28a593350047845a45a14cc5026221ac1620James Dong 2664d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2665d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2666d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2667d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2668fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang // For video, skip the first several non-key frames until getting the first key frame. 2669fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mIsVideo && !mGotStartKeyFrame && !isSync) { 2670fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang ALOGD("Video skip non-key frame"); 2671fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang copy->release(); 2672fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang continue; 2673fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2674fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang if (mIsVideo && isSync) { 2675fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang mGotStartKeyFrame = true; 2676fe44e4f74fe2582cbf012687059278dbcbdaa6f7Hangyu Kuang } 2677d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2678c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 267970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2680f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2681f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 26828428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 26833c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 268448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2685a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 26868428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 268711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) { 268811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2689d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 26909db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 26919db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 269211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 269311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 26948428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 269511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) { 269611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2697d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 26989db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 26999db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 270011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 270111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 27028428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2703a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2704a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2705a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2706a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 270711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 270811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2709d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 27109db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 27119db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 271211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 271311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 271425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo) { 2715965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2716965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2717965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2718000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 2719965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 2720965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 2721965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2722965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 2723826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar 2724826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar // ensure non-negative, monotonic decoding time 2725826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar if (mLastDecodingTimeUs < 0) { 2726826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar decodingTimeUs = std::max((int64_t)0, decodingTimeUs); 2727826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar } else { 2728826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar // increase decoding time by at least 1 tick 2729826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar decodingTimeUs = std::max( 2730826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar mLastDecodingTimeUs + divUp(1000000, mTimeScale), decodingTimeUs); 2731826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar } 2732826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar 2733826cbe4d07c709f647cdd29354434df20e355c9aLajos Molnar mLastDecodingTimeUs = decodingTimeUs; 2734000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 2735000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 273611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) { 273711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2738d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 27399db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 27409db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 274111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 274211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2743965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 2744a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64, 2745000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 2746000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2747000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 2748000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 2749000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 275011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) { 275111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2752d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 27539db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 27549db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 275511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 275611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2757c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 275843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 275943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 276043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 276143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 276243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 276343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 276443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 276543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 276643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 276743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 276843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 276943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 277043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 277143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 277243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 2773000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2774000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 2775c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 2776000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2777000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2778000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 2779000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2780000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2781000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2782000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2783000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2784000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2785000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2786965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2787872a481558350634a3fd5cb67939de288af00ecbJames Dong 2788de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2789872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2790872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 2791e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2792e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2793872a481558350634a3fd5cb67939de288af00ecbJames Dong 279411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 279511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2796d24affe100fb9ebcdabef47068e7a0f728a3a44eHangyu Kuang mSource->stop(); 27979db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 27989db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 279911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 280011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2801a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64, 280211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, previousPausedDurationUs); 2803c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2804c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 28053b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 28063b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 28075a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 28085a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 28095a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 28105a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 28115a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 28125a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 28135a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 28145a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2815c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 2816f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track", 2817f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang (long long)timestampUs, (long long)lastTimestampUs, trackName); 281811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 28190332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang mSource->stop(); 28209db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang mIsMalformed = true; 28219db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang break; 28228c460498c028888c533ab442be12b6d4b669b965James Dong } 28238c460498c028888c533ab442be12b6d4b669b965James Dong 282485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // if the duration is different for this sample, see if it is close enough to the previous 282585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // duration that we can fudge it and use the same value, to avoid filling the stts table 282685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // with lots of near-identical entries. 282785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // "close enough" here means that the current duration needs to be adjusted by less 282885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // than 0.1 milliseconds 282985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { 283085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL 283185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen + (mTimeScale / 2)) / mTimeScale; 283285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (deltaUs > -100 && deltaUs < 100) { 283385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // use previous ticks, and adjust timestamp as if it was actually that number 283485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // of ticks 283585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen currDurationTicks = lastDurationTicks; 283685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen timestampUs += deltaUs; 283785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 283885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 2839c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 2840c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 2841c059860c73678a202bfa33062723e8f82fb779d9James Dong 2842a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2843a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2844c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 284579761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2846be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2847be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2848be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2849be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2850965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2851be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2852be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2853c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2854be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2855be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 28568644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2857be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2858a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64, 285911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, lastTimestampUs); 28608644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2861c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 28628644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 286320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2864d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 2865c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 2866d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2867d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 286893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 286993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 287093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 287193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2872faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 287393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 287443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 287580f78b773f92048944a850efb7b60629643370cdPraveen Chavan off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy) 287658ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 2877c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2878c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count = (mOwner->use32BitFileOffset() 2879c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 2880c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 2881c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2882c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (count == 0) { 28831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 288458ae9c530247668f8af36e30d228c716c226b3d4James Dong } 288558ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 288658ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 288758ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 288858ae9c530247668f8af36e30d228c716c226b3d4James Dong } 288913aec890216948b0c364f8f92792129d0335f506James Dong 289013aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 289113aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 28921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 28931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 289413aec890216948b0c364f8f92792129d0335f506James Dong } else { 289513aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 289613aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 289713aec890216948b0c364f8f92792129d0335f506James Dong } else { 289843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 289943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 290043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 290143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 290243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 290313aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 290413aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 2905c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 2906c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 2907c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 290813aec890216948b0c364f8f92792129d0335f506James Dong } 29091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 291013aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 291113aec890216948b0c364f8f92792129d0335f506James Dong } 291213aec890216948b0c364f8f92792129d0335f506James Dong } 291313aec890216948b0c364f8f92792129d0335f506James Dong } 291413aec890216948b0c364f8f92792129d0335f506James Dong 291520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 291625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 291745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 2918690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2919f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 292045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2921bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2922be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 292313aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 292443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2925c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(1, mStszTableEntries->count()); 292658ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 29271f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 29281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 292913aec890216948b0c364f8f92792129d0335f506James Dong } 293013aec890216948b0c364f8f92792129d0335f506James Dong 2931be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2932be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2933be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2934c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 1) { 29358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 293679761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2937be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2938be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2939be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2940a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2941c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() <= 2) { 294279761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2943a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 294479761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2945a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2946a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 294779761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2948a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2949a472613aec322e25891abf5c77bf3f7e3c244920James Dong 295043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // The last ctts box may not have been written yet, and this 295143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // is to make sure that we write out the last ctts box. 295243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 295343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (cttsSampleCount > 0) { 295443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 295543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 295643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 295743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 2958c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 295925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 296043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 296143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 296243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2963df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 296411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih count, nZeroLengthFrames, mStszTableEntries->count(), trackName); 2965872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2966a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs()); 2967872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2968365a963142093a1cd8efdcea76b5f65096a5b115James Dong 296937187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 297037187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 297137187916a486504acaf83bea30147eb5fbf46ae5James Dong } 297237187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2973365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2974365a963142093a1cd8efdcea76b5f65096a5b115James Dong 297545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 29769db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang if (mIsMalformed) { 29779db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang return true; 29789db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang } 29799db9f8d45ed2f22917dc6cf03b582b98add4510bHangyu Kuang 2980c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { // no samples written 298129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 298245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 298345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 298445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 298525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo && mStssTableEntries->count() == 0) { // no sync frames for video 298629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 298745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 298845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 298945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 299045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 299145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 299245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 299345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 299445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 299545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 299645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 299743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 299807ec01904613a0bac32caaa8444b4690998faed7James Dong 299907ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 300007ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 300107ec01904613a0bac32caaa8444b4690998faed7James Dong return; 300207ec01904613a0bac32caaa8444b4690998faed7James Dong } 300307ec01904613a0bac32caaa8444b4690998faed7James Dong 300443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 300543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 300643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 300743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 300825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mIsAudio ? 0: 1); 300943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 301043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 301143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 301243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 301343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 301443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 301543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 3016c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 301743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 301886b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 301986b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 302086b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 302186b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 302286b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 302386b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 302486b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 302586b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 302686b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 302786b7f47aa7482424cf8fd248f1315311919be3b0James Dong 302886b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 302970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 303070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 303186b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 303270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 303307ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 303407ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 303507ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 303607ec01904613a0bac32caaa8444b4690998faed7James Dong 303743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 303843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 303943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 304043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 304170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 304270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 304370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 304470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 304570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 304670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 304770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 304870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 304943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 305043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 305143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 3052faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 3053a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("trackProgressStatus: %" PRId64 " us", timeUs); 3054c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 3055215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 3056215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 3057a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs); 3058bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 305993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 306093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 306193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 306293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 3063faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 3064bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 3065faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 3066bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 3067faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 3068faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 3069faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 3070faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 3071bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 3072bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 3073faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 3074faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 3075faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 3076faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 3077faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 3078faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 3079bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3080bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 3081faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 3082faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 3083faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 3084bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 3085bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 3086faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 3087faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 3088faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 3089faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 3090d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 3091a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs); 3092e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 3093d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 3094e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 3095e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 3096e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 3097a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs); 3098e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 3099e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 3100e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 3101e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 3102de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const { 3103de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui return mIsRealTimeRecording; 3104de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui} 3105de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 3106b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 3107b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 3108b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 3109b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 31101c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 31113856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 31121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 31131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 31141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 311513aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 311620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 311720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31183b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 3119c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 312020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 312120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3122d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 3123d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 3124d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 3125d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 3126690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 3127690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 3128690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 3129690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 3130690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 31319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) || 31329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 3133690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 3134690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 313529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 3136690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 3137690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 3138690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 3139690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 3140690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 314129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 3142690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 3143690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 3144690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 3145690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 3146690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 3147690f546b0ee548dbfe997df36418e5302ec2d786James Dong 314825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangconst char *MPEG4Writer::Track::getTrackType() const { 314925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang return mIsAudio ? "Audio" : (mIsVideo ? "Video" : "Metadata"); 315025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang} 31518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 315225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 3153efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 3154b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 3155b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 3156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 3157b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 3158b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 3159b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 3160b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 3161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 316225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (mIsVideo) { 3163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 316425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else { 316525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang writeNmhdBox(); 3166b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3167b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 3168b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 3169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 3170b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 3171b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 3172b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3173b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3174b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 3175b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 3176b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 3177b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3178b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 3179b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 3180b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 318125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else if (mIsVideo) { 3182b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 318325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } else { 318425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang writeMetadataFourCCBox(); 3185b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3186b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 3187b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 318825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (mIsVideo) { 318925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang writeCttsBox(); 3190b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 3191b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3192b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 3193b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 3194b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 3195b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 3196b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3197b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 319825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeMetadataFourCCBox() { 319925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *mime; 320025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang bool success = mMeta->findCString(kKeyMIMEType, &mime); 320125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang CHECK(success); 320225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang const char *fourcc = getFourCCForMime(mime); 320325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (fourcc == NULL) { 320425adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang ALOGE("Unknown mime type '%s'.", mime); 320525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang TRESPASS(); 320625adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang } 320725adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->beginBox(fourcc); // TextMetaDataSampleEntry 320825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeCString(mime); // metadata mime_format 320925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->endBox(); // mett 321025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang} 321125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang 3212b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 3213b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 3214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 3215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 32168b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 32178b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 321829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 321925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang TRESPASS(); 3220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 32228b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan mOwner->beginBox(fourcc); // video format 3223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 3226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 3229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 3230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 3231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 3233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 3234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 3235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 3238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 3239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 3240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 3241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 3243c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->writeInt8(0); // compressor string length 3244c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->write(" ", 31); 3245b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 3246b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 3247b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3248b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 3249b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 3250b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 3251b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 3252b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 3253b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 32549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 32559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim writeHvccBox(); 3256b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3257b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3258b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 325958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar writeColrBox(); 3260b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 3261b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3262b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 326358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() { 326458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar ColorAspects aspects; 326558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar memset(&aspects, 0, sizeof(aspects)); 326658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar // TRICKY: using | instead of || because we want to execute all findInt32-s 326758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries) 326858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer) 326958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs) 327058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) { 327158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar int32_t primaries, transfer, coeffs; 327258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar bool fullRange; 327358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar ColorUtils::convertCodecColorAspectsToIsoAspects( 327458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar aspects, &primaries, &transfer, &coeffs, &fullRange); 327558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->beginBox("colr"); 327658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeFourcc("nclx"); 327758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(primaries); 327858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(transfer); 327958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(coeffs); 3280fffb0c8fbe16ac948619b85e1eea9e65a9daa0c9Pirama Arumuga Nainar mOwner->writeInt8(int8_t(fullRange ? 0x80 : 0x0)); 328158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->endBox(); // colr 328258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar } 328358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar} 328458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar 3285b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 3286b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 3287b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 3288b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 32898b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 32908b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 329129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 329225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang TRESPASS(); 3293b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3294b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3295b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 3296b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3297b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3298b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 3299b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 3302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 3303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 3304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 3305b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3307b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 3309b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 3310b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3311b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 3312b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 3313b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 3314b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 3315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 3316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 3317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3318b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3319b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 3322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 3323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 332443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 3325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 332743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(mCodecSpecificDataSize + 23, 128); 3328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 3331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 3332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 3333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 3334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 3337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 3338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 3339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 334146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt8(0x00); // buffer size 24-bit (0x300) 334246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 334396bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t avgBitrate = 0; 334446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 334596bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t maxBitrate = 0; 334646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 334746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(maxBitrate); 334846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(avgBitrate); 3349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 3352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 3355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 3356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 3357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 3358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 3360b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 3362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3363b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 3365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 336643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 3367bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan 3368bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan // Make sure all sizes encode to a single byte. 3369bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan CHECK_LT(23 + mCodecSpecificDataSize, 128); 3370bc4e708bf8c160d8a3388125a8238ea2768aeadePraveen Chavan 3371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 3372b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 3376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 3377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 3378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 3379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 3382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 3383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 3384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 338646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 0x01, 0x77, 0x00, // buffer size 96000 bytes 3387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 3389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 339096bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t avgBitrate = 0; 339146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 339296bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t maxBitrate = 0; 339346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 339446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(maxBitrate); 339546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(avgBitrate); 339646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 3397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 3400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 3403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 3404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 3405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 3406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 3408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 3410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3412efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 3413b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 3414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 3415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 3416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 3417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 3418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 3419219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 3420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 34218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 3422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 3423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 3424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 3425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 3426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 3429b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 3430b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 3431b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3433b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 343420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 343525adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang if (!mIsVideo) { 3436b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 3437b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 3438b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 3439b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 3440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 3441b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 3442b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3443b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3444b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 3445b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 3446b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3447b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 3448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3449b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3450b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 3451b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 3452b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 3453b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 3454b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 3455b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 3456b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 3457b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3458b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3459b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3460b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 3461b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 3462b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3463b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 3464b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3465b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3466b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3467b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 346825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuangvoid MPEG4Writer::Track::writeNmhdBox() { 346925adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->beginBox("nmhd"); 347025adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeInt32(0); // version=0, flags=0 347125adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->endBox(); 347225adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang} 347325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang 3474b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 3475b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 3476b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3477b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 347825adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeFourcc(mIsAudio ? "soun" : (mIsVideo ? "vide" : "meta")); // component subtype 3479b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3482b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 348325adc33c1ba77b95162ebce8a4c2a7a07baeb98fHangyu Kuang mOwner->writeCString(mIsAudio ? "SoundHandle": (mIsVideo ? "VideoHandle" : "MetadHandle")); 3484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3487efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 3488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 3489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 3490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 3492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 3493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 3494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 3495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 3496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 3497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 3498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 3499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 3500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 3501decc50efede28c5d73137c30d1a95d72dd405555David Yeh const char *lang = NULL; 3502decc50efede28c5d73137c30d1a95d72dd405555David Yeh int16_t langCode = 0; 3503decc50efede28c5d73137c30d1a95d72dd405555David Yeh if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) { 3504decc50efede28c5d73137c30d1a95d72dd405555David Yeh langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f); 3505decc50efede28c5d73137c30d1a95d72dd405555David Yeh } 3506decc50efede28c5d73137c30d1a95d72dd405555David Yeh mOwner->writeInt16(langCode); // language code 3507b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 3512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 3513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 3514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 3515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3516b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 3517b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 3518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 3519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 3523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 3524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 3525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 3526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 3527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 3528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 3531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 3532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 3534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 3535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 3536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3537b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 3539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 3540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 3541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 3542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 3545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 354643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mCodecSpecificDataSize, 5); 3547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 3549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 3550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 3551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 3552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 3553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 3555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3556b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 35579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 35589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() { 35599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim CHECK(mCodecSpecificData); 35609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim CHECK_GE(mCodecSpecificDataSize, 5); 35619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 35629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Patch avcc's lengthSize field to match the number 35639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // of bytes we use to indicate the size of a nal unit. 35649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim uint8_t *ptr = (uint8_t *)mCodecSpecificData; 35659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 35669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->beginBox("hvcC"); 35679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 35689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->endBox(); // hvcC 35699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 35709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 3571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 3572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 3573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 3574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 3576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 3577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 3578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 3581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 3582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 3583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 3584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 3585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 3586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3588000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 3589a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 3590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3591b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 359243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 3593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3595000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 3596000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 3597000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3598000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 3599000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 3600000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3601c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3602c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mSttsTableEntries->get(duration, 1)); 3603c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back to host byte order 3604c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 3605c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 3606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 3607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 360820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3609965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 3610000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 3611000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 3612000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 3613000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 3614000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3615965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 3616c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 3617965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3618965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3619965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3620a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]", 3621c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 3622965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3623965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 3624000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3625c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t delta = mMinCttsOffsetTimeUs - getStartTimeOffsetScaledTime(); 3626c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) { 3627c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar // entries are <count, ctts> pairs; adjust only ctts 3628c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar uint32_t duration = htonl(value[1]); // back to host byte order 3629c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar value[1] = htonl(duration - delta); 3630c259a4027f151fc57d7b09b62d62cb133ba11d05Lajos Molnar }); 3631c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 3632965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 3633965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 3634965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 3636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 3637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3638c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 3639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 3640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 364125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 3642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 3643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 3644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3645c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 3646c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 3647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 3648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 364920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 3651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 3652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3653c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 3654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 3655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 365620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 3658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 3659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3660c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 3661c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 3662c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 3663c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 3664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 366620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 366720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 366807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 366907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 367007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 367107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 367207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 367307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 3674e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() { 3675e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("hdlr"); 3676e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3677e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Predefined 3678e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3679e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[0] 3680e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[1] 3681e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[2] 3682e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt8(0); // Name (empty) 3683e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3684e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3685e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3686e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() { 3687e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3688e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3689e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("keys"); 3690e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3691e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(count); // Entry_count 3692e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3693e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3694e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3695e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t n = strlen(key); 3696e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(n + 8); 3697e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3698e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang write(key, n); // write without the \0 3699e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3700e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3701e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3702e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3703e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() { 3704e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3705e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3706e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("ilst"); 3707e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3708e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox(i + 1); // key id (1-based) 3709e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("data"); 3710e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3711e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3712e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang switch (type) { 37137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang case AMessage::kTypeString: 37147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang { 37157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang AString val; 37167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang CHECK(mMetaKeys->findString(key, &val)); 37177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(1); // type = UTF8 37187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 37197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang write(val.c_str(), strlen(val.c_str())); // write without \0 37207c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang break; 37217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 37227c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 3723e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeFloat: 3724e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3725e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang float val; 3726e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findFloat(key, &val)); 37277c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(23); // type = float32 37287c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3729e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(*reinterpret_cast<int32_t *>(&val)); 3730e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3731e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3732e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3733e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeInt32: 3734e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3735e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang int32_t val; 3736e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findInt32(key, &val)); 37377c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(67); // type = signed int32 37387c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3739e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(val); 3740e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3741e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3742e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3743e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang default: 3744e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3745e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang ALOGW("Unsupported key type, writing 0 instead"); 37467c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(77); // type = unsigned int32 37477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3748e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 3749e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3750e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3751e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3752e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // data 3753e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // key id 3754e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3755e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // ilst 3756e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3757e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3758e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() { 3759e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3760e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (count == 0) { 3761e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return; 3762e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3763e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3764e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("meta"); 3765e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeHdlr(); 3766e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeKeys(); 3767e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeIlst(); 3768e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3769e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3770e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 377107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 377207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 377307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 377407b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 377507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 377607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 377707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 377807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 377907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 3780432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 3781432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 378207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 378307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 378407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 378507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 378607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 378707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 378807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 378907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 379020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3791