MPEG4Writer.cpp revision 10cc12c4eec9ff974edb72f9140b05762fa50907
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 2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h> 21a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <fcntl.h> 22a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h> 2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h> 24a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/prctl.h> 25a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/stat.h> 26a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <sys/types.h> 27a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <unistd.h> 28a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn 29a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <utils/Log.h> 3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong#include <media/stagefright/foundation/ADebug.h> 32e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang#include <media/stagefright/foundation/AMessage.h> 3358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar#include <media/stagefright/foundation/ColorUtils.h> 3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 3718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 3803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h> 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 41d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h> 4207ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h> 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h" 459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include "include/HevcUtils.h" 4680f78b773f92048944a850efb7b60629643370cdPraveen Chavan#include "include/avc_utils.h" 47dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn 48dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false 49dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0) 50dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif 51dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn 5211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \ 53dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \ 5411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih ALOGW("Condition %s failed " message, #condition, ##__VA_ARGS__); \ 5511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih true; \ 5611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih})) 5711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6077e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024; 611f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32 621f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad // filesystem file size 631f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad // used by most SD cards 643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07; 653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08; 6670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs = 700000LL; 675b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong 687c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[] = "com.android.version"; 693b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#ifdef SHOW_MODEL_BUILD 703b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[] = "com.android.model"; 717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[] = "com.android.build"; 723b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif 737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps"; 744dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatic const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count"; 757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kMandatoryHevcNalUnitTypes[3] = { 779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeVps, 789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeSps, 799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypePps, 809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}; 819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = { 829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeVps, 839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeSps, 849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypePps, 859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypePrefixSei, 869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim kHevcNalUnitTypeSuffixSei, 879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}; 887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang/* uncomment to include model and build in meta */ 897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1 907c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 93b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen Track(MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId); 948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 9837187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t stop(); 9937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 10025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1023b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 103d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 104b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTrackHeader(bool use32BitOffset = true); 1051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 1061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 1079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bool isHevc() const { return mIsHevc; } 1081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 1091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 110c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong void addChunkOffset(off64_t offset); 11170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int32_t getTrackId() const { return mTrackId; } 112dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 1138b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan static const char *getFourCCForMime(const char *mime); 11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 116000e18370baae60ffd9f25b509501dd8c26deabfJames Dong enum { 117000e18370baae60ffd9f25b509501dd8c26deabfJames Dong kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 1188c460498c028888c533ab442be12b6d4b669b965James Dong kSampleArraySize = 1000, 119000e18370baae60ffd9f25b509501dd8c26deabfJames Dong }; 120000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // A helper class to handle faster write box with table entries 122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong template<class TYPE> 123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong struct ListTableEntries { 124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity) 125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mElementCapacity(elementCapacity), 126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEntryCapacity(entryCapacity), 127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTotalNumTableEntries(0), 128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry(0), 129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement(NULL) { 130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mElementCapacity, 0); 131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mEntryCapacity, 0); 1322177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia // Ensure no integer overflow on allocation in add(). 1332177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia CHECK_LT(mEntryCapacity, UINT32_MAX / mElementCapacity); 134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Free the allocated memory. 137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ~ListTableEntries() { 138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (!mTableEntryList.empty()) { 139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete[] (*it); 141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.erase(it); 142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Replace the value at the given position by the given value. 146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // There must be an existing value at the given position. 147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order 148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void set(const TYPE& value, uint32_t pos) { 15025f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity); 151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value; 162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Get the value at the given position by the given value. 165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value the retrieved value at the position in network byte order. 166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @return true if a value is found. 168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool get(TYPE& value, uint32_t pos) const { 16925f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong if (pos >= mTotalNumTableEntries * mEntryCapacity) { 170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return false; 171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong value = (*it)[(pos % (mElementCapacity * mEntryCapacity))]; 183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return true; 184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Store a single value. 187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order. 188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void add(const TYPE& value) { 189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nValues = mNumValuesInCurrEntry % mEntryCapacity; 192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries == 0 && nValues == 0) { 193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity]; 194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCurrTableEntriesElement != NULL); 195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.push_back(mCurrTableEntriesElement); 196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t pos = nEntries * mEntryCapacity + nValues; 199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement[pos] = value; 200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mNumValuesInCurrEntry; 202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) { 203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mTotalNumTableEntries; 204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry = 0; 205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Write out the table entries: 209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 1. the number of entries goes first 210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 2. followed by the values in the table enties in order 211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg writer the writer to actual write to the storage 212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void write(MPEG4Writer *writer) const { 213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0); 214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries; 215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->writeInt32(nEntries); 216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong it != mTableEntryList.end(); ++it) { 218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(nEntries, 0); 219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries >= mElementCapacity) { 220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity); 221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong nEntries -= mElementCapacity; 222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries); 224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong break; 225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Return the number of entries in the table. 230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count() const { return mTotalNumTableEntries; } 231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong private: 233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mElementCapacity; // # entries in an element 234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mEntryCapacity; // # of values in each entry 235c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mTotalNumTableEntries; 236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mNumValuesInCurrEntry; // up to mEntryCapacity 237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong TYPE *mCurrTableEntriesElement; 238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mutable List<TYPE *> mTableEntryList; 239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong }; 242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 247b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen sp<IMediaSource> mSource; 24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 249a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 250a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 251eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 2521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 2539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bool mIsHevc; 2541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 2551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 256bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 257c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 25843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 259e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 260d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 2611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 2628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 266be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 26713aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 2681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 269c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool mSamplesHaveSameSize; 270c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStszTableEntries; 271be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 272c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStcoTableEntries; 273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<off64_t> *mCo64TableEntries; 274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStscTableEntries; 275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStssTableEntries; 276c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mSttsTableEntries; 277c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mCttsTableEntries; 278965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 279000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMinCttsOffsetTimeUs; 280000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMaxCttsOffsetTimeUs; 281965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 2833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 2843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 2853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 2863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 2873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 2883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 2893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 2903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 2913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 2923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 2933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 2943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 2953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 298548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 29993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 3023c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 30370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 30470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 30593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 30693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 30725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 308872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 309872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 310872a481558350634a3fd5cb67939de288af00ecbJames Dong 311000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int32_t getStartTimeOffsetScaledTime() const; 312000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 31437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 3173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 3183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 3199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t copyCodecSpecificData(const uint8_t *data, size_t size, size_t minLength = 0); 3209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 324215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 3259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t makeHEVCCodecSpecificData(const uint8_t *data, size_t size); 3269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t copyHEVCCodecSpecificData(const uint8_t *data, size_t size); 3279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t parseHEVCCodecSpecificData( 3289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, HevcParameterSets ¶mSets); 3299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 330215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 331faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 33293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 33303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 33419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 33519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 336c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 337c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 338c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 339c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 340c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 341c059860c73678a202bfa33062723e8f82fb779d9James Dong 342690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 343690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 34413f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t mRotation; 345690f546b0ee548dbfe997df36418e5302ec2d786James Dong 3461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 3471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 3481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 34979761ab096f57c3027fad9556c2bc436672d614eJames Dong 35079761ab096f57c3027fad9556c2bc436672d614eJames Dong // Duration is time scale based 35179761ab096f57c3027fad9556c2bc436672d614eJames Dong void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 352965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 35345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 35445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong bool isTrackMalFormed() const; 35543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 3561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 360b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 363965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void writeCttsBox(); 364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 366b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 3679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim void writeHvccBox(); 368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 372efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeMdhdBox(uint32_t now); 373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 376efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeTkhdBox(uint32_t now); 37758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar void writeColrBox(); 378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 38420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 38830ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 389674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(dup(fd)), 390674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(mFd < 0? NO_INIT: OK), 391de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording(true), 392b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 3931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 394a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 395a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 396a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 397411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 39830ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 39913aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 400e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mMoovBoxBuffer(NULL), 401e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mMoovBoxBufferOffset(0), 402e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mWriteMoovBoxToMemory(false), 403e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mFreeBoxOffset(0), 404e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mStreamableFile(false), 4057837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 4067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize(0), 40707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 408e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mTimeScale(-1), 409e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mStartTimestampUs(-1ll), 41007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 41107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 41286b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 413ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar mStartTimeOffsetMs(-1), 414ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar mMetaKeys(new AMessage()) { 4157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang addDeviceMeta(); 4162aa74dc097fe860abc84769abf2b6e0962718471Robert Shih 4172aa74dc097fe860abc84769abf2b6e0962718471Robert Shih // Verify mFd is seekable 4182aa74dc097fe860abc84769abf2b6e0962718471Robert Shih off64_t off = lseek64(mFd, 0, SEEK_SET); 4192aa74dc097fe860abc84769abf2b6e0962718471Robert Shih if (off < 0) { 4202aa74dc097fe860abc84769abf2b6e0962718471Robert Shih ALOGE("cannot seek mFd: %s (%d)", strerror(errno), errno); 4212aa74dc097fe860abc84769abf2b6e0962718471Robert Shih release(); 4222aa74dc097fe860abc84769abf2b6e0962718471Robert Shih } 42330ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 42430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 42520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 4268bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong reset(); 42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 4291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 4311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 4321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 437dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 438dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 439dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 440dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 441dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 442dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 443dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 444dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 445dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 446dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 447dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 448dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 449dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 450dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 451dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 452dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 453dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 454dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 45584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber int fd, const Vector<String16>& /* args */) const { 456dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 457dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 458dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 459dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 460dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 461dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 462dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 463dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 464c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 46513210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 466377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); 46713210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 468dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 469dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 470dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 471dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 4728b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static 4738b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) { 4748b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (mime == NULL) { 4758b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 4768b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 4778b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strncasecmp(mime, "audio/", 6)) { 4788b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 4798b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "samr"; 4808b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 4818b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "sawb"; 4828b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 4838b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4a"; 4848b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 4858b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strncasecmp(mime, "video/", 6)) { 4868b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 4878b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4v"; 4888b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 4898b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "s263"; 4908b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 4918b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "avc1"; 4929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 4939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return "hvc1"; 4948b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 4958b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else { 4968b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan ALOGE("Track (%s) other than video or audio is not supported", mime); 4978b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 4988b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 4998b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan} 5008b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan 501b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissenstatus_t MPEG4Writer::addSource(const sp<IMediaSource> &source) { 502bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 503bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 50429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Attempt to add source AFTER recording is started"); 505bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 506bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 507acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 508acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // At most 2 tracks can be supported. 509acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.size() >= 2) { 510a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGE("Too many tracks (%zu) to add", mTracks.size()); 511acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 512acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 513acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 514acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong CHECK(source.get() != NULL); 515acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 516acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong const char *mime; 517acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong source->getFormat()->findCString(kKeyMIMEType, &mime); 518acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong bool isAudio = !strncasecmp(mime, "audio/", 6); 5198b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (Track::getFourCCForMime(mime) == NULL) { 5208b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan ALOGE("Unsupported mime '%s'", mime); 521acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 522acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 523acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 524acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // At this point, we know the track to be added is either 525acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // video or audio. Thus, we only need to check whether it 526acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // is an audio track or not (if it is not, then it must be 527acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // a video track). 528acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 529acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // No more than one video or one audio track is supported. 530acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong for (List<Track*>::iterator it = mTracks.begin(); 531acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong it != mTracks.end(); ++it) { 532acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if ((*it)->isAudio() == isAudio) { 533acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("%s track already exists", isAudio? "Audio": "Video"); 534acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 535acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 536acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 537acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 538acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // This is the first track of either audio or video. 539acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // Go ahead to add the track. 540219f195159f93d627af2b243732e3f9020511a46James Dong Track *track = new Track(this, source, 1 + mTracks.size()); 54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 5422dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 5432dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 54693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 547acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.empty()) { 548acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("No source added"); 549acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return INVALID_OPERATION; 550acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 551acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 552a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 553a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 55493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 555a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 556a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 557a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 558a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 559a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 560a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 561a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 562a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 563a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 564a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 565a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 566a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 567a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 5687c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() { 5697c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // add device info and estimate space in 'moov' 5707c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang char val[PROPERTY_VALUE_MAX]; 5717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size_t n; 5727c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // meta size is estimated by adding up the following: 5737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - meta header structures, which occur only once (total 66 bytes) 5747c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - size for each key, which consists of a fixed header (32 bytes), 5757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // plus key length and data length. 5767c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 66; 5777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.version.release", val, NULL) 5787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 5797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Version, val, n + 1); 5807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32; 5817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 5827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD 5837c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.product.model", val, NULL) 5847c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 5857c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Model, val, n + 1); 5867c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32; 5877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 5887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.display.id", val, NULL) 5897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 5907c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Build, val, n + 1); 5917c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32; 5927c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 5937c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif 5947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang} 5957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 5962dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 5972dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 5982dec2b5be2056c6d9428897dc672185872d30d17James Dong // 5992dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 6002dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 6012dec2b5be2056c6d9428897dc672185872d30d17James Dong 60278a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 6032dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 60478a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 6052dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 6062dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 6072dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 6082dec2b5be2056c6d9428897dc672185872d30d17James Dong 6092dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 6102dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 6112dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 61278a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 6132dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 6142dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 6152dec2b5be2056c6d9428897dc672185872d30d17James Dong 61678a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 617a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 61878a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 61978a1a286f736888ae7af8860b2c424af0d978848James Dong } 62078a1a286f736888ae7af8860b2c424af0d978848James Dong 62178a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 62278a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 62378a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 62478a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 62578a1a286f736888ae7af8860b2c424af0d978848James Dong ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000); 62678a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 62778a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 62878a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 62978a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 63078a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 63178a1a286f736888ae7af8860b2c424af0d978848James Dong } 63278a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 63378a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 63478a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 63578a1a286f736888ae7af8860b2c424af0d978848James Dong } 6362dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6372dec2b5be2056c6d9428897dc672185872d30d17James Dong } 63878a1a286f736888ae7af8860b2c424af0d978848James Dong 6392dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 6402dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 6412dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6422dec2b5be2056c6d9428897dc672185872d30d17James Dong 6432dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 6442dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 6452dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 6462dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 6472dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6482dec2b5be2056c6d9428897dc672185872d30d17James Dong 6497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // Account for the extra stuff (Geo, meta keys, etc.) 6507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size += mMoovExtraSize; 6517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 652a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the" 653a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn " estimated moov size %" PRId64 " bytes", 6542dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 6552dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 6562dec2b5be2056c6d9428897dc672185872d30d17James Dong} 6572dec2b5be2056c6d9428897dc672185872d30d17James Dong 6582dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 659674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 66025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 663a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 664a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 665a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 666a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 667a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 668a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 669a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 670a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 671a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 672a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 6732dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 6742dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 6752dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 6762dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 6772dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 6782dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6792dec2b5be2056c6d9428897dc672185872d30d17James Dong 6801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 6811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 6821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 6831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 6841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 6861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 6871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 6881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 689a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. " 690a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn "It is changed to %" PRId64 " bytes", 691d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 692d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 6931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 696b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 697b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 698b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 699b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 700b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 7012dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7022dec2b5be2056c6d9428897dc672185872d30d17James Dong 703de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui int32_t isRealTimeRecording; 704de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) { 705de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording = isRealTimeRecording; 706de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 707de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 708065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 70993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 710a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 711a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 712a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 71393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 714a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 715a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 716a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 717a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 7188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 7198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 7208f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 7218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 72243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 7233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("movie time scale: %d", mTimeScale); 7248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 72577e8ae9967a078770416619e99ddb5b010def312James Dong /* 72677e8ae9967a078770416619e99ddb5b010def312James Dong * When the requested file size limit is small, the priority 72777e8ae9967a078770416619e99ddb5b010def312James Dong * is to meet the file size limit requirement, rather than 7287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to make the file streamable. mStreamableFile does not tell 7297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * whether the actual recorded file is streamable or not. 73077e8ae9967a078770416619e99ddb5b010def312James Dong */ 73177e8ae9967a078770416619e99ddb5b010def312James Dong mStreamableFile = 73277e8ae9967a078770416619e99ddb5b010def312James Dong (mMaxFileSizeLimitBytes != 0 && 73377e8ae9967a078770416619e99ddb5b010def312James Dong mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 73477e8ae9967a078770416619e99ddb5b010def312James Dong 7357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong /* 7367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory is true if the amount of data in moov box is 7377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * smaller than the reserved free space at the beginning of a file, AND 7387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * when the content of moov box is constructed. Note that video/audio 7397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * frame data is always written to the file but not in the memory. 7407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Before stop()/reset() is called, mWriteMoovBoxToMemory is always 7427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * false. When reset() is called at the end of a recording session, 7437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Moov box needs to be constructed. 7447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory 7467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to set to mStreamableFile so that if 7477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the file is intended to be streamable, it is set to true; 7487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * otherwise, it is set to false. When the value is set to false, 7497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * all the content of the moov box is written immediately to 7507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the end of the file. When the value is set to true, all the 7517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * content of the moov box is written to an in-memory cache, 7527b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mMoovBoxBuffer, util the following condition happens. Note 7537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * that the size of the in-memory cache is the same as the 7547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * reserved free space at the beginning of the file. 7557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 2) While the data of the moov box is written to an in-memory 7577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache, the data size is checked against the reserved space. 7587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * If the data size surpasses the reserved space, subsequent moov 7597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * data could no longer be hold in the in-memory cache. This also 7607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * indicates that the reserved space was too small. At this point, 7617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * _all_ moov data must be written to the end of the file. 7627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory must be set to false to direct the write 7637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to the file. 7647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 3) If the data size in moov box is smaller than the reserved 7667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space after moov box is completely constructed, the in-memory 7677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache copy of the moov box is written to the reserved free 7687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space. Thus, immediately after the moov is completedly 7697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * constructed, mWriteMoovBoxToMemory is always set to false. 7707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong */ 7717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 7727837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 7737837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 7747837c17063a4c50bc856ba59418516fdab731de7James Dong 775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7777837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7797837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 7802dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 7812dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 7822dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 7832dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7842dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 7857837c17063a4c50bc856ba59418516fdab731de7James Dong } 78643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mEstimatedMoovBoxSize, 8); 78777e8ae9967a078770416619e99ddb5b010def312James Dong if (mStreamableFile) { 78877e8ae9967a078770416619e99ddb5b010def312James Dong // Reserve a 'free' box only for streamable file 78977e8ae9967a078770416619e99ddb5b010def312James Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 79077e8ae9967a078770416619e99ddb5b010def312James Dong writeInt32(mEstimatedMoovBoxSize); 79177e8ae9967a078770416619e99ddb5b010def312James Dong write("free", 4); 79277e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 79377e8ae9967a078770416619e99ddb5b010def312James Dong } else { 79477e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mOffset; 79577e8ae9967a078770416619e99ddb5b010def312James Dong } 7967837c17063a4c50bc856ba59418516fdab731de7James Dong 7977837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 798c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 7991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 8001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 8011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 8021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 8031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 8041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 8061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 8071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 8081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 811a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 812a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 8141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 815a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 81625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 8201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 8211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 82337187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 824674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 82537187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 826a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 827a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 82837187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 829a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 830a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 83137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 83237187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 83337187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 83437187916a486504acaf83bea30147eb5fbf46ae5James Dong } 835a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 83637187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 837a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 838a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 8391c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 840b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping writer thread"); 841411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 842411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 843411ba422e3635d534928ffd81abf54f4f291c739James Dong } 8441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 8461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 8471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 8491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 8501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 8531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 854411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 855b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Writer thread stopped"); 8561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 8571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 85813f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 85913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 86013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 86113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 86213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 86313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 86413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 86513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 86613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 86713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 86813f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 86913f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 8703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeCompositionMatrix"); 87113f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 87213f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 87313f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 87413f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 87513f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 87613f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 87713f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 87813f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 87913f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 88013f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 88113f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 88213f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 88313f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 88413f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 88513f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 88613f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 88713f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 88813f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 88913f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 89013f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 89113f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 89213f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 89313f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 89413f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 89513f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 89613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 89713f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 89813f6284305e4b27395a23db7882d670bdb1bcae1James Dong 89913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 90013f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 90113f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 90213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 90313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 90413f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 90513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 90613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 90713f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 90813f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 90913f6284305e4b27395a23db7882d670bdb1bcae1James Dong 910411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 911411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 912411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 913411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 914411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 9154c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary free(mMoovBoxBuffer); 9164c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary mMoovBoxBuffer = NULL; 917411ba422e3635d534928ffd81abf54f4f291c739James Dong} 91813f6284305e4b27395a23db7882d670bdb1bcae1James Dong 9198bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() { 920674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 92137187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 922411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 923411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 924411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 925411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 926411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 927411ba422e3635d534928ffd81abf54f4f291c739James Dong } 928411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 929411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 930411ba422e3635d534928ffd81abf54f4f291c739James Dong } 93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 93337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 9348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 93565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 93620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 93720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 93837187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 93937187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 94037187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 94137187916a486504acaf83bea30147eb5fbf46ae5James Dong } 94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 9448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 9458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 94620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 94765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 94865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 94965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 95065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 95165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 95265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 953a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us", 95465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 9587837c17063a4c50bc856ba59418516fdab731de7James Dong 95937187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 96037187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 961411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 96237187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 96337187916a486504acaf83bea30147eb5fbf46ae5James Dong } 96437187916a486504acaf83bea30147eb5fbf46ae5James Dong 96520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 9661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 967c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 9681f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); 969c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 9701acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 971c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 9721f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint64_t size = mOffset - mMdatOffset; 9731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 974c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 9751acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 976c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Construct moov box now 9797837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 9807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = mStreamableFile; 9817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 9827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // There is no need to allocate in-memory cache 9837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // for moov box if the file is not streamable. 9847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 9857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 9867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong CHECK(mMoovBoxBuffer != NULL); 9877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 98920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // mWriteMoovBoxToMemory could be set to false in 9917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // MPEG4Writer::write() method 9927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 9937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 9947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Content of the moov box is saved in the cache, and the in-memory 9957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // moov box needs to be written to the file in a single shot. 9967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 99743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 9987837c17063a4c50bc856ba59418516fdab731de7James Dong 9997837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 1000c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 10017837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 1002674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 10037837c17063a4c50bc856ba59418516fdab731de7James Dong 10047837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 1005c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 10067837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 10077837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 10087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } else { 10097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ALOGI("The mp4 file will not be streamable."); 10107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 10117837c17063a4c50bc856ba59418516fdab731de7James Dong 10127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Free in-memory cache for moov box 10137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mMoovBoxBuffer != NULL) { 10147837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 10157837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 10167837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 10177837c17063a4c50bc856ba59418516fdab731de7James Dong } 10187837c17063a4c50bc856ba59418516fdab731de7James Dong 10190c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 102020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1021411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 102237187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1025efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() { 1026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 1027efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 1028efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // while time function returns Unix epoch values which starts 1029efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // at 1970-01-01. Lets add the number of seconds between them 10302b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60); 10312b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen if (now < 0 || uint32_t(now) > UINT32_MAX - delta) { 10322b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen return 0; 10332b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen } 10342b3b672cf57657640ece98810cb34ae2bfa91e14Marco Nelissen uint32_t mpeg4Time = uint32_t(now) + delta; 1035efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson return mpeg4Time; 1036efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson} 1037efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson 1038efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 1039efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 1040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 1041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 1042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 1043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 1044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 1045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 1046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 1047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 1048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 1049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 1050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 1053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 1060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 1061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 1064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 1065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 106607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 106707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 106807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 1069e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeMetaBox(); 1070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 1071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 1072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 1073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 1074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 1076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 10782cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 1079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 1080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 1082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 1083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 1084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 10858284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 10868284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("isom"); 10878284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("3gp4"); 1088b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 10898284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 10908284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 1091b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 10928284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 1093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1094b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 1096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 109807ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 109907ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 110007ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 110107ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 110207ec01904613a0bac32caaa8444b4690998faed7James Dong 110307ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 110407ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 110507ec01904613a0bac32caaa8444b4690998faed7James Dong char value[PROPERTY_VALUE_MAX]; 110607ec01904613a0bac32caaa8444b4690998faed7James Dong if (property_get("rw.media.record.test", value, NULL) && 110707ec01904613a0bac32caaa8444b4690998faed7James Dong (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 110807ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 110907ec01904613a0bac32caaa8444b4690998faed7James Dong } 111007ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 111107ec01904613a0bac32caaa8444b4690998faed7James Dong} 111207ec01904613a0bac32caaa8444b4690998faed7James Dong 111370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 111407ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 111507ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 111607ec01904613a0bac32caaa8444b4690998faed7James Dong return; 111707ec01904613a0bac32caaa8444b4690998faed7James Dong } 111807ec01904613a0bac32caaa8444b4690998faed7James Dong 111970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 112070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 112170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 112270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 112370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 112470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 112570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 112670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 112770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 112813aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 112913aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 113013aec890216948b0c364f8f92792129d0335f506James Dong return OK; 113113aec890216948b0c364f8f92792129d0335f506James Dong} 113213aec890216948b0c364f8f92792129d0335f506James Dong 113313aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 113413aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 113513aec890216948b0c364f8f92792129d0335f506James Dong} 113613aec890216948b0c364f8f92792129d0335f506James Dong 113713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 113813aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 113913aec890216948b0c364f8f92792129d0335f506James Dong} 114020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1141c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 1142c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1144c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1145c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1146c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 114720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 114820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 114920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 115120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 115220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 115403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 115503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 115603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 115703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 115803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 115903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 116003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 116103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 116203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 116303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 116403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 116503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 116603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 116780f78b773f92048944a850efb7b60629643370cdPraveen Chavanoff64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) { 116880f78b773f92048944a850efb7b60629643370cdPraveen Chavan off64_t old_offset = mOffset; 116980f78b773f92048944a850efb7b60629643370cdPraveen Chavan 117080f78b773f92048944a850efb7b60629643370cdPraveen Chavan const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs 117180f78b773f92048944a850efb7b60629643370cdPraveen Chavan 117280f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset(); 117380f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *currentNalStart = dataStart; 117480f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *nextNalStart; 117580f78b773f92048944a850efb7b60629643370cdPraveen Chavan const uint8_t *data = dataStart; 117680f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t nextNalSize; 117780f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ? 117880f78b773f92048944a850efb7b60629643370cdPraveen Chavan kExtensionNALSearchRange : buffer->range_length(); 117980f78b773f92048944a850efb7b60629643370cdPraveen Chavan 118080f78b773f92048944a850efb7b60629643370cdPraveen Chavan while (getNextNALUnit(&data, &searchSize, &nextNalStart, 118180f78b773f92048944a850efb7b60629643370cdPraveen Chavan &nextNalSize, true) == OK) { 118210cc12c4eec9ff974edb72f9140b05762fa50907Lajos Molnar size_t currentNalSize = nextNalStart - currentNalStart - 4 /* strip start-code */; 118380f78b773f92048944a850efb7b60629643370cdPraveen Chavan MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize); 118480f78b773f92048944a850efb7b60629643370cdPraveen Chavan addLengthPrefixedSample_l(nalBuf); 118580f78b773f92048944a850efb7b60629643370cdPraveen Chavan nalBuf->release(); 118680f78b773f92048944a850efb7b60629643370cdPraveen Chavan 118780f78b773f92048944a850efb7b60629643370cdPraveen Chavan currentNalStart = nextNalStart; 118880f78b773f92048944a850efb7b60629643370cdPraveen Chavan } 118980f78b773f92048944a850efb7b60629643370cdPraveen Chavan 119080f78b773f92048944a850efb7b60629643370cdPraveen Chavan size_t currentNalOffset = currentNalStart - dataStart; 119180f78b773f92048944a850efb7b60629643370cdPraveen Chavan buffer->set_range(buffer->range_offset() + currentNalOffset, 119280f78b773f92048944a850efb7b60629643370cdPraveen Chavan buffer->range_length() - currentNalOffset); 119380f78b773f92048944a850efb7b60629643370cdPraveen Chavan addLengthPrefixedSample_l(buffer); 119480f78b773f92048944a850efb7b60629643370cdPraveen Chavan 119580f78b773f92048944a850efb7b60629643370cdPraveen Chavan return old_offset; 119680f78b773f92048944a850efb7b60629643370cdPraveen Chavan} 119780f78b773f92048944a850efb7b60629643370cdPraveen Chavan 1198c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 1199c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 120030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 120130ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 120203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1203b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 1204b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 1205c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1206b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 1207c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1208b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 1209c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1210b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1211c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1212c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 1213c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1214c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1215c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 1216b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1217b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 1218b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 121943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(length, 65536); 122030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1221b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 1222c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1223b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1224c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1225c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1226b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 1227b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 122830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 122930ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 123030ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 123130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 12327837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 1233674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 12347837c17063a4c50bc856ba59418516fdab731de7James Dong 12357837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 12367837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 12377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 1238c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 12391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 12407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // The reserved moov box at the beginning of the file 12417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // is not big enough. Moov box should be written to 12427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the end of the file from now on, but not to the 12437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // in-memory cache. 12447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 12457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // We write partial moov box that is in the memory to 12467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the file first. 1247c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 12487837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 12497837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 12507837c17063a4c50bc856ba59418516fdab731de7James Dong } 1251674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 1252674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 12537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ::write(mFd, ptr, bytes); 12547837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 12557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 12567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // All subsequent moov box content will be written 12577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // to the end of the file. 12587837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 12597837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 12607837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 12617837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 12627837c17063a4c50bc856ba59418516fdab731de7James Dong } 12637837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1264674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 12657837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 12667837c17063a4c50bc856ba59418516fdab731de7James Dong } 12677837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 12687837c17063a4c50bc856ba59418516fdab731de7James Dong} 12697837c17063a4c50bc856ba59418516fdab731de7James Dong 1270e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) { 1271e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mBoxes.push_back(mWriteMoovBoxToMemory? 1272e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mMoovBoxBufferOffset: mOffset); 1273e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 1274e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 1275e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(id); 1276e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1277e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 12790c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12817837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 12827837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 128320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 12890c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1291c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12947837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 12957837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 12967837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 12977837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1298c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 12997837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 13007837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1301c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 13027837c17063a4c50bc856ba59418516fdab731de7James Dong } 130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 130520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1306674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 130920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 131020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1311674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 131520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1316674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1321674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1326674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 13300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 1331674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 133507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 133607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 133707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 133807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 133907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 134007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 134107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 134207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 134307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 134407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 134507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 134607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 134707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 134807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 134907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 135007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 135107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 135207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 135307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 135407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 135507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 135607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 135707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 135807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 135907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 136007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 136107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 136207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 136307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 136407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 136507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 136607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 136707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 136807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 136907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 137007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 137107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 137207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 137307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 137407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 137507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 137607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 137707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 137807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 137907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 138007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 138107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 138207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 138307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 138407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 138507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 138607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 138707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 138807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 138907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 139007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 139107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 139207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 139307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 139407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 139507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 139607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 139707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 139807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 139907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 140007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 140107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 14027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 30; 140307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 140407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 140507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 1406e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) { 1407e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (captureFps <= 0.0f) { 1408e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return BAD_VALUE; 1409e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 1410e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 14117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps); 14127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32; 14137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 1414e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return OK; 1415e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1416e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 14174dbff11975e737482537e1636051690188f3fbc4Praveen Chavanstatus_t MPEG4Writer::setTemporalLayerCount(uint32_t layerCount) { 14184dbff11975e737482537e1636051690188f3fbc4Praveen Chavan if (layerCount > 9) { 14194dbff11975e737482537e1636051690188f3fbc4Praveen Chavan return BAD_VALUE; 14204dbff11975e737482537e1636051690188f3fbc4Praveen Chavan } 14214dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 14224dbff11975e737482537e1636051690188f3fbc4Praveen Chavan if (layerCount > 0) { 14234dbff11975e737482537e1636051690188f3fbc4Praveen Chavan mMetaKeys->setInt32(kMetaKey_TemporalLayerCount, layerCount); 14244dbff11975e737482537e1636051690188f3fbc4Praveen Chavan mMoovExtraSize += sizeof(kMetaKey_TemporalLayerCount) + 4 + 32; 14254dbff11975e737482537e1636051690188f3fbc4Praveen Chavan } 14264dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 14274dbff11975e737482537e1636051690188f3fbc4Praveen Chavan return OK; 14284dbff11975e737482537e1636051690188f3fbc4Praveen Chavan} 14294dbff11975e737482537e1636051690188f3fbc4Praveen Chavan 143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1431674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 143220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 143478a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 143578a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 143678a1a286f736888ae7af8860b2c424af0d978848James Dong} 143778a1a286f736888ae7af8860b2c424af0d978848James Dong 1438d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1439d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1440d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1441d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1442d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1443d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1444956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1445d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1446d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1447d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1448d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 14491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 145077e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 145177e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 145277e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 145377e8ae9967a078770416619e99ddb5b010def312James Dong } 1454acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1455acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1456acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1457acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1458d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1459d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1460d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1461d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1462d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1463d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1464d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1465d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1466d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1467d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1468d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1469d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1470d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1471d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1472d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1473d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1474d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 147525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 147625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 147725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 147825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 147925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 148025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 148125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 148225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 148325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 148425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 148525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 148625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 148725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1488f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1489a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("setStartTimestampUs: %" PRId64, timeUs); 149043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 14913c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1492065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1493f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1494a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs); 14953c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 14963c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 14973c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1498f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 14993c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 15003c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 15013c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 15023c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 150358ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 150458ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 150558ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 150658ae9c530247668f8af36e30d228c716c226b3d4James Dong} 150758ae9c530247668f8af36e30d228c716c226b3d4James Dong 150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 150920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 151020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1511b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId) 151220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 151325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 151420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 151520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1516a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1517a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1518eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1519bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1520c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1521956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1522be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1523c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1524c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1525c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)), 1526c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)), 1527c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1528c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 1529c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 153125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1532548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 153313f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 153413f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 153519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 15368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 15371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 15381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 15391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 15409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC); 15411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 15421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 15431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 15441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1545c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1546c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1547c059860c73678a202bfa33062723e8f82fb779d9James Dong 15481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 15491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1550c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1551c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 1552c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 1553c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1554c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 15551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 155678a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 155778a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 155878a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 155978a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1560c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1561c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1562c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1563c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 156478a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 156578a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 156678a1a286f736888ae7af8860b2c424af0d978848James Dong } 15671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 15681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 15691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 15701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 15711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1572c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(chunkId)); 1573c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(sampleId)); 1574c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(1)); 15751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 15761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 15771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1578c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 15791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 15801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 15811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 158279761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 15831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 15845a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 1585377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGW("0-duration samples found: %zu", sampleCount); 15865a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1587c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1588c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 15891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 15901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1591965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1592965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1593965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1594965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { 1595965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1596965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1597c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1598c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1599965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1600965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1601c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1602c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1603c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1604c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1605c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1606c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1607c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 16081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 16091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1610c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 16113856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 1612c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1613c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1614c059860c73678a202bfa33062723e8f82fb779d9James Dong 1615c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1616c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1617c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1618c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1619c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1620c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1621c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1622c059860c73678a202bfa33062723e8f82fb779d9James Dong 1623c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1624c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1625c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1626c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1627c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1628c059860c73678a202bfa33062723e8f82fb779d9James Dong 162943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 163019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 163119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 163219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 163319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 163419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 163519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 16369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim uint32_t type; 16379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const void *data = NULL; 16389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t size = 0; 163919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 16409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mMeta->findData(kKeyAVCC, &type, &data, &size); 16419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) { 16429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mMeta->findData(kKeyHVCC, &type, &data, &size); 164319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 164419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 164519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 164619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 16479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (esds.getCodecSpecificInfo(&data, &size) != OK) { 16489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim data = NULL; 16499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size = 0; 165019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 165119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 165219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 16539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) { 16549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mGotAllCodecSpecificData = true; 16559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 165620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 165720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 165820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 165920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 166020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1661c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 1662c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 1663c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 1664c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 1665c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 1666c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 1667c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 1668c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 1669c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 1670c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 1671c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 1672c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 1673c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 1674c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 1675c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 1676c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 167720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 167820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 167920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 168020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 168120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 168220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 168393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 16843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 168593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 168693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 168793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 168893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 168993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 169093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 1691a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs); 169293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 169393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 169493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 169593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 169693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 169793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 16981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 16991c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 17003856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 17011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 17021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 17031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 17041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17061c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 17073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 17081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 17091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 17101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 17121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 17131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 17151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 17161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 17171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 17181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 172143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 17221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1724fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1725a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("writeChunkToFile: %" PRId64 " from %s track", 17265410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video"); 1727fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1728fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1729fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1730fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1731fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 17329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc()) 173380f78b773f92048944a850efb7b60629643370cdPraveen Chavan ? addMultipleLengthPrefixedSamples_l(*it) 1734fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1735fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1736fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1737fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1738fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 17391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 17421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1743fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 17441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1745fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 17461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1748fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 17493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 17501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 175170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 175270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1753e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 175470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 17551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 175670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 175770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 175870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 17591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 1760377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGD("%zu chunks are written in the last batch", outstandingChunks); 17611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1763fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 17643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 17651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 17671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 17681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 17691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 17701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 17711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 17721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 17731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 17751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 17803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 1781fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 17821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 17851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 17861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1787fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 17881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 17891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 17901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1791fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1792fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1793fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 179470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 179570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 179670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 179770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 179870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 179970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 180070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1801fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 18021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 18031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1804fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1805fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 18061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 18071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18081c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 18093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 18101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1811a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1812fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1813fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 18141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1815fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1816fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1817fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1818fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 18191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 18201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 18211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1822de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // In real time recording mode, write without holding the lock in order 1823de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // to reduce the blocking time for media track threads. 1824de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // Otherwise, hold the lock until the existing chunks get written to the 1825de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // file. 1826fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 1827de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1828de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.unlock(); 1829de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1830fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 1831de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1832de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.lock(); 1833de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1834fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 18351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1836fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1837fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 18381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 18391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18401c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 18413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 18421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 18441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1845e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 18461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 18471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 18481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 18491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 185070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 185170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 18521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 18531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 18541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 18561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 18571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 18581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 18591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 1860411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 18611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 18621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 18631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 18641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 186593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1866a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1867a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1868a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1869a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1870a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 187125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 187293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 187319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 187419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 187519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 187670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 187719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 187813f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 187913f6284305e4b27395a23db7882d670bdb1bcae1James Dong if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 188013f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 188113f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 188213f6284305e4b27395a23db7882d670bdb1bcae1James Dong 188393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 188493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1885f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1886de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 1887a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 1888a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 1889a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 1890a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 1891a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 1892a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 189386b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 189486b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 1895a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 189686b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 189786b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 189886b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 189986b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 190086b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 1901a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs); 1902a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 1903a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1904f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1905a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1906f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 190725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 190825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 190925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 191025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 191120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 191220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 191320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 191420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 191520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 191620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1917eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 1918c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 191925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1920956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 19211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 192243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 192320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 192425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 192520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 192625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 192725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 192820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 192920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 193037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1931a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 193237187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1933a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1934a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 193537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 193672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track stopping", mIsAudio? "Audio": "Video"); 1937eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 193829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 1939eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 1940eaae38445a340c4857c1c5569475879a728e63b7James Dong } 1941eaae38445a340c4857c1c5569475879a728e63b7James Dong 194220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 194337187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 194420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 194520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 194620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 194772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track source stopping", mIsAudio? "Audio": "Video"); 194872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mSource->stop(); 194972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track source stopped", mIsAudio? "Audio": "Video"); 195072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 195120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 195220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 1953377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 195437187916a486504acaf83bea30147eb5fbf46ae5James Dong 1955b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%s track stopped", mIsAudio? "Audio": "Video"); 195637187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 195720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 195820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 195925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 196025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 196125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 196225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 196320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 196420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 196520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 196620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 196737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 1968377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT return (void *)(uintptr_t)err; 196920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 197020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 19723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 19733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 19753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 19763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 19773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 19793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 19803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 19823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 19833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 19843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 198547d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar const uint8_t *nextStartCode = findNextNalStartCode(data, length); 19863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 19873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 198829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 19893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 19903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 19933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 19943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 199529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 19963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 19973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 19993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 20003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 20013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 20033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 20053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 200607b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar // COULD DO: set profile/level to the lowest required to support all SPSs 200729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 20123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 20163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 20193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 20203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 20233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 20249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyCodecSpecificData(data, size, 4 + 7); 20259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 20269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 20279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyHEVCCodecSpecificData( 20289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size) { 20299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGV("copyHEVCCodecSpecificData"); 20309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 20319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Min length of HEVC CSD is 23. (ISO/IEC 14496-15:2014 Chapter 8.3.3.1.2) 20329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyCodecSpecificData(data, size, 23); 20339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 20349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 20359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::copyCodecSpecificData( 20369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, size_t minLength) { 20379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (size < minLength) { 2038377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 20439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 20449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 20459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 20469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 20479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = size; 20483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 20493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 20503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 20513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 20533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 20543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20553856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 20563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 20573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 20583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 20593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 20603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 20613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 20623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 20633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 20643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 20653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 20663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 20673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 20683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 20693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 20703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 207129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 20723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 20753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 20763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 20783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 20793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 208029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 20813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 20843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 20853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 20873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 208829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 20933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 20973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 20983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 20993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 21003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 21033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 21043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 21053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 210629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 21073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 21083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 2111377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 21123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 21133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 21173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 21183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 21193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 212029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 21213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 21223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 2124377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 21253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 21263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21281374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 21291374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 21301374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 21311374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 21323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 21333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 21343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 21353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 21363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 213729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 21383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 21393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21411374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 21423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 21433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 2144548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 214503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 214603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 2147548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 214803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 214929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 215003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 215103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 215203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 21533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 2154377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 215503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 215603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 215703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 21583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 21593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 21603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 216103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 216203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 21633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 216403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 216503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 216603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 21673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 21683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 216903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 21709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 21719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = 0; 21729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 21739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 21749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 217503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 21763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 21773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 21783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 21793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 218003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 21813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2182b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2183b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 2184b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2185b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 2186b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 218703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 21883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 21893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 21903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 21913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 21923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 21933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 21943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 21953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 21963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 21973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 21983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 22003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 22013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 22023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 22033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 22053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 22063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 22073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 22083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 22093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 22103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 22113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 22123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 22133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 22143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 22153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 22163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 22173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 22183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 221903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 222003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 222103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 222203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 22239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::parseHEVCCodecSpecificData( 22259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size, HevcParameterSets ¶mSets) { 22269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGV("parseHEVCCodecSpecificData"); 22289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *tmp = data; 22299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *nextStartCode = data; 22309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t bytesLeft = size; 22319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 223247d8891199f40a3a89c2910e4407f82a125df43bLajos Molnar nextStartCode = findNextNalStartCode(tmp + 4, bytesLeft - 4); 22339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t err = paramSets.addNalUnit(tmp + 4, (nextStartCode - tmp) - 4); 22349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (err != OK) { 22359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 22369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Move on to find the next parameter set 22399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim bytesLeft -= nextStartCode - tmp; 22409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim tmp = nextStartCode; 22419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t csdSize = 23; 22449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const size_t numNalUnits = paramSets.getNumNalUnits(); 22459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t i = 0; i < ARRAY_SIZE(kMandatoryHevcNalUnitTypes); ++i) { 22469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim int type = kMandatoryHevcNalUnitTypes[i]; 22479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 22489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (numParamSets == 0) { 22499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Cound not find NAL unit of type %d", type); 22509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 22519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) { 22549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim int type = kHevcNalUnitTypes[i]; 22559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim size_t numParamSets = paramSets.getNumNalUnitsOfType(type); 22569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (numParamSets > 0xffff) { 22579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Too many seq parameter sets (%zu) found", numParamSets); 22589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 22599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim csdSize += 3; 22619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim for (size_t j = 0; j < numNalUnits; ++j) { 22629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (paramSets.getType(j) != type) { 22639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim continue; 22649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim csdSize += 2 + paramSets.getSize(j); 22669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = csdSize; 22699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return OK; 22709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 22719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t MPEG4Writer::Track::makeHEVCCodecSpecificData( 22739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim const uint8_t *data, size_t size) { 22749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData != NULL) { 22769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Already have codec specific data"); 22779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 22789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (size < 4) { 22819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Codec specific data length too short: %zu", size); 22829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 22839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Data is in the form of HEVCCodecSpecificData 22869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (memcmp("\x00\x00\x00\x01", data, 4)) { 22879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return copyHEVCCodecSpecificData(data, size); 22889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim HevcParameterSets paramSets; 22919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (parseHEVCCodecSpecificData(data, size, paramSets) != OK) { 22923d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim ALOGE("failed parsing codec specific data"); 22939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return ERROR_MALFORMED; 22949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 22959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 22969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificData = malloc(mCodecSpecificDataSize); 22979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mCodecSpecificData == NULL) { 22989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mCodecSpecificDataSize = 0; 22999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ALOGE("Failed allocating codec specific data"); 23009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return NO_MEMORY; 23019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 23029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim status_t err = paramSets.makeHvcc((uint8_t *)mCodecSpecificData, 23033d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim &mCodecSpecificDataSize, mOwner->useNalLengthFour() ? 4 : 2); 23049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (err != OK) { 23053d53e1c0dd7760f3ca58ff75e74cd7fcf4bc08ccWonsik Kim ALOGE("failed constructing HVCC atom"); 23069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return err; 23079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } 23089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 23099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim return OK; 23109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 23119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 2312872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 2313872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 2314872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 2315872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 2316872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 2317872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2318872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 2319872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 2320872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2321872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 2322872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2323872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2324872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2325872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 2326872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2327872a481558350634a3fd5cb67939de288af00ecbJames Dong} 2328872a481558350634a3fd5cb67939de288af00ecbJames Dong 232937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 233030ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 233113aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 233243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 233313aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 233413aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 23357c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar int32_t nActualFrames = 0; // frames containing non-CSD data (non-0 length) 233613aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 2337965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 2338965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 2339965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 2340965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 2341965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 2342000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 2343a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 2344965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 2345000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 2346000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2347000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 234843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2349c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 2350e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2351a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 2352a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 2353a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } else { 2354a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 2355a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 2356de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2357de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2358de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2359de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2360985f838934510983d8a887461e98dca60a6e858fJames Dong 2361d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 236220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 236393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 236420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 236511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih const char *trackName = mIsAudio ? "Audio" : "Video"; 236693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 236720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 236820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 236920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 237013aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 237120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 237220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 237320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2374a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 2375a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 2376a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2377a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2378a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2379a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2380a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2381a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2382a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 238330ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 238430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 238503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 238603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 238703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 23887c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // if config format (at track addition) already had CSD, keep that 23897c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // UNLESS we have not received any frames yet. 23907c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // TODO: for now the entire CSD has to come in one frame for encoders, even though 23917c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar // they need to be spread out for decoders. 23927c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar if (mGotAllCodecSpecificData && nActualFrames > 0) { 23937c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar ALOGI("ignoring additional CSD for video track after first frame"); 23947c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else { 23957c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar mMeta = mSource->getFormat(); // get output format after format change 23967c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar 23977c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar if (mIsAvc) { 23987c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar status_t err = makeAVCCodecSpecificData( 23997c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar (const uint8_t *)buffer->data() 24007c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar + buffer->range_offset(), 24017c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 24027c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar CHECK_EQ((status_t)OK, err); 24037c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else if (mIsHevc) { 24047c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar status_t err = makeHEVCCodecSpecificData( 24057c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar (const uint8_t *)buffer->data() 24067c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar + buffer->range_offset(), 24077c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 24087c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar CHECK_EQ((status_t)OK, err); 24097c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } else if (mIsMPEG4) { 24107c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(), 24117c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar buffer->range_length()); 24127c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar } 241330ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 241430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 241530ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 241630ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 241730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2418548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 241930ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2420a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2421a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 24227c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar ++nActualFrames; 24237c9ea89cbe3e42e0d94b1790ae1d424a9c16ce08Lajos Molnar 2424d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2425d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2426d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2427d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2428d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2429d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2430d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2431d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2432d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2433d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 24349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mIsAvc || mIsHevc) StripStartcode(copy); 2435e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2436b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 24379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim if (mIsAvc || mIsHevc) { 2438b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2439b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2440b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2441b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2442b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2443b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2444050b28a593350047845a45a14cc5026221ac1620James Dong 2445d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 24461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 24471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 24481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2449d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2450316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang ALOGW("Recorded file size exceeds limit %" PRId64 "bytes", 2451316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang mOwner->mMaxFileSizeLimitBytes); 2452d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2453d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2454d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2455d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2456316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds", 2457316d08c1f115499fb0ccd82d22592bed7e54aad7Hangyu Kuang mOwner->mMaxFileDurationLimitUs); 2458d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2459d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2460d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2461d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2462050b28a593350047845a45a14cc5026221ac1620James Dong 2463d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2464d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2465d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2466d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2467d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2468c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 246970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2470f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2471f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 24728428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 24733c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 247448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2475a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 24768428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 247711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) { 247811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 247911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 248011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 248111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 24828428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 248311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) { 248411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 248511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 248611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 248711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 24888428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2489a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2490a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2491a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2492a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 249311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 249411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 249511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 249611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 249711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2498000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (!mIsAudio) { 2499965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2500965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2501965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2502000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 2503965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 2504965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 2505965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2506965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 2507000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 2508000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 250911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) { 251011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 251111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 251211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 251311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2514965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 2515a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64, 2516000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 2517000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2518000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 2519000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 2520000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 252111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) { 252211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 252311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 252411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 252511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2526c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 252743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 252843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 252943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 253043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 253143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 253243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 253343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 253443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 253543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 253643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 253743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 253843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 253943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 254043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 254143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 2542000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2543000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 2544c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 2545000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2546000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2547000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 2548000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2549000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2550000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2551000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2552000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2553000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2554000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2555965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2556872a481558350634a3fd5cb67939de288af00ecbJames Dong 2557de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2558872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2559872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 2560e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2561e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2562872a481558350634a3fd5cb67939de288af00ecbJames Dong 256311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 256411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 256511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 256611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 256711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2568a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64, 256911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, previousPausedDurationUs); 2570c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2571c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 25723b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 25733b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 25745a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 25755a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 25765a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 25775a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 25785a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 25795a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 25805a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 25815a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2582c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 2583f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track", 2584f85a83af8c6a98b46c394c32b90b09214a68f3e4Hangyu Kuang (long long)timestampUs, (long long)lastTimestampUs, trackName); 258511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 25860332fadec6e91c37fe39ab92b2c02922370bc853Hangyu Kuang mSource->stop(); 2587c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return UNKNOWN_ERROR; 25888c460498c028888c533ab442be12b6d4b669b965James Dong } 25898c460498c028888c533ab442be12b6d4b669b965James Dong 259085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // if the duration is different for this sample, see if it is close enough to the previous 259185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // duration that we can fudge it and use the same value, to avoid filling the stts table 259285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // with lots of near-identical entries. 259385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // "close enough" here means that the current duration needs to be adjusted by less 259485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // than 0.1 milliseconds 259585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { 259685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL 259785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen + (mTimeScale / 2)) / mTimeScale; 259885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (deltaUs > -100 && deltaUs < 100) { 259985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // use previous ticks, and adjust timestamp as if it was actually that number 260085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // of ticks 260185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen currDurationTicks = lastDurationTicks; 260285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen timestampUs += deltaUs; 260385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 260485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 260585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen 2606c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 2607c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 2608c059860c73678a202bfa33062723e8f82fb779d9James Dong 2609a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2610a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2611c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 261279761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2613be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2614be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2615be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2616be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2617965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2618be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2619be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2620c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2621be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2622be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 26238644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2624be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2625a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64, 262611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, lastTimestampUs); 26278644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2628c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 26298644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 263020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2631d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 2632c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 2633d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2634d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 263593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 263693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 263793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 263893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2639faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 264093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 264143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 264280f78b773f92048944a850efb7b60629643370cdPraveen Chavan off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy) 264358ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 2644c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2645c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count = (mOwner->use32BitFileOffset() 2646c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 2647c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 2648c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2649c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (count == 0) { 26501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 265158ae9c530247668f8af36e30d228c716c226b3d4James Dong } 265258ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 265358ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 265458ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 265558ae9c530247668f8af36e30d228c716c226b3d4James Dong } 265613aec890216948b0c364f8f92792129d0335f506James Dong 265713aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 265813aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 26591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 26601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 266113aec890216948b0c364f8f92792129d0335f506James Dong } else { 266213aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 266313aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 266413aec890216948b0c364f8f92792129d0335f506James Dong } else { 266543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 266643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 266743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 266843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 266943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 267013aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 267113aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 2672c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 2673c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 2674c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 267513aec890216948b0c364f8f92792129d0335f506James Dong } 26761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 267713aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 267813aec890216948b0c364f8f92792129d0335f506James Dong } 267913aec890216948b0c364f8f92792129d0335f506James Dong } 268013aec890216948b0c364f8f92792129d0335f506James Dong } 268113aec890216948b0c364f8f92792129d0335f506James Dong 268220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 268325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 268445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 2685690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2686f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 268745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2688bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2689be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 269013aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 269143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2692c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(1, mStszTableEntries->count()); 269358ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 26941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 26951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 269613aec890216948b0c364f8f92792129d0335f506James Dong } 269713aec890216948b0c364f8f92792129d0335f506James Dong 2698be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2699be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2700be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2701c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 1) { 27028f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 270379761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2704be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2705be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2706be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2707a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2708c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() <= 2) { 270979761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2710a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 271179761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2712a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2713a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 271479761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2715a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2716a472613aec322e25891abf5c77bf3f7e3c244920James Dong 271743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // The last ctts box may not have been written yet, and this 271843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // is to make sure that we write out the last ctts box. 271943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 272043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (cttsSampleCount > 0) { 272143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 272243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 272343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 272443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 2725c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 272625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 272743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 272843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 272943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2730df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 273111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih count, nZeroLengthFrames, mStszTableEntries->count(), trackName); 2732872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2733a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs()); 2734872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2735365a963142093a1cd8efdcea76b5f65096a5b115James Dong 273637187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 273737187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 273837187916a486504acaf83bea30147eb5fbf46ae5James Dong } 273937187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2740365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2741365a963142093a1cd8efdcea76b5f65096a5b115James Dong 274245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 2743c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { // no samples written 274429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 274545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 274645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 274745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2748c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (!mIsAudio && mStssTableEntries->count() == 0) { // no sync frames for video 274929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 275045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 275145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 275245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 275345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 275445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 275545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 275645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 275745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 275845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 275945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 276043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 276107ec01904613a0bac32caaa8444b4690998faed7James Dong 276207ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 276307ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 276407ec01904613a0bac32caaa8444b4690998faed7James Dong return; 276507ec01904613a0bac32caaa8444b4690998faed7James Dong } 276607ec01904613a0bac32caaa8444b4690998faed7James Dong 276743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 276843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 276943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 277043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 277143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mIsAudio? 0: 1); 277243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 277343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 277443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 277543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 277643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 277743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 277843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2779c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 278043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 278186b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 278286b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 278386b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 278486b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 278586b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 278686b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 278786b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 278886b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 278986b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 279086b7f47aa7482424cf8fd248f1315311919be3b0James Dong 279186b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 279270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 279370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 279486b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 279570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 279607ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 279707ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 279807ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 279907ec01904613a0bac32caaa8444b4690998faed7James Dong 280043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 280143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 280243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 280343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 280470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 280570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 280670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 280770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 280870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 280970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 281070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 281170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 281243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 281343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 281443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2815faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 2816a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("trackProgressStatus: %" PRId64 " us", timeUs); 2817c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2818215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 2819215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 2820a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs); 2821bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 282293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 282393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 282493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 282593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2826faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 2827bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 2828faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 2829bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 2830faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2831faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 2832faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 2833faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 2834bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2835bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2836faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2837faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 2838faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2839faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2840faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 2841faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 2842bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2843bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2844faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2845faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 2846faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 2847bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2848bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2849faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 2850faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2851faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 2852faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2853d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 2854a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs); 2855e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2856d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 2857e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2858e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2859e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 2860a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs); 2861e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2862e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 2863e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2864e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2865de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const { 2866de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui return mIsRealTimeRecording; 2867de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui} 2868de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2869b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 2870b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 2871b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 2872b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 28731c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 28743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 28751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 28761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 28771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 287813aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 287920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 288020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 28813b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 2882c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 288320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 288420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2885d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2886d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 2887d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 2888d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2889690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 2890690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 2891690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2892690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2893690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 28949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) || 28959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 2896690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2897690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 289829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 2899690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2900690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2901690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2902690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2903690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 290429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 2905690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2906690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2907690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2908690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2909690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2910690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 291220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29133856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s track time scale: %d", 29141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 29158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 2916efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 2923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 2925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 2929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 2930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 2931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 2932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 2933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 2937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 2938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 2940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 2942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 2946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 2947965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong writeCttsBox(); 2948b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mIsAudio) { 2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 2955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 29618b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 29628b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 296329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 29678b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan mOwner->beginBox(fourcc); // video format 2968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 2971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 2979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 2983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 2984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 2985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 2986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 2988c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->writeInt8(0); // compressor string length 2989c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->write(" ", 31); 2990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 2991b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 2992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 299343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(23 + mCodecSpecificDataSize, 128); 2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 30019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) { 30029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim writeHvccBox(); 3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 300658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar writeColrBox(); 3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 301058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarvoid MPEG4Writer::Track::writeColrBox() { 301158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar ColorAspects aspects; 301258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar memset(&aspects, 0, sizeof(aspects)); 301358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar // TRICKY: using | instead of || because we want to execute all findInt32-s 301458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries) 301558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer) 301658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs) 301758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) { 301858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar int32_t primaries, transfer, coeffs; 301958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar bool fullRange; 302058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar ColorUtils::convertCodecColorAspectsToIsoAspects( 302158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar aspects, &primaries, &transfer, &coeffs, &fullRange); 302258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->beginBox("colr"); 302358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeFourcc("nclx"); 302458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(primaries); 302558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(transfer); 302658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt16(coeffs); 302758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->writeInt8(fullRange ? 128 : 0); 302858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar mOwner->endBox(); // colr 302958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar } 303058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar} 303158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar 3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 30368b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 30378b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 303829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 3039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 3040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 3043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 3046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 3049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 3050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 3051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 3052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 3057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 3060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 3061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 3062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 3063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 3064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 3069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 3070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 307143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 307443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(mCodecSpecificDataSize + 23, 128); 3075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 3078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 3079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 3080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 3081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 3084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 3085b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 3086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3087b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 308846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt8(0x00); // buffer size 24-bit (0x300) 308946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 309096bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t avgBitrate = 0; 309146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 309296bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t maxBitrate = 0; 309346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 309446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(maxBitrate); 309546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(avgBitrate); 3096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3097b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3098b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 3099b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3100b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3101b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 3102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 3103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 3104b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 3105b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3106b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 3107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 3109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3111b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 3112b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 311343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 3114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 3115b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3116b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3117b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3118b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 3119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 3120b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 3121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 3122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3123b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 3124b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 3125b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 3126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 3127b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 312946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 0x01, 0x77, 0x00, // buffer size 96000 bytes 3130b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 3132b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 313396bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t avgBitrate = 0; 313446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyBitRate, &avgBitrate); 313596bdf620189622005e83b4f1421c4f25b7fa1729Lajos Molnar int32_t maxBitrate = 0; 313646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate); 313746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(maxBitrate); 313846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar mOwner->writeInt32(avgBitrate); 313946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar 3140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 3141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 3143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3145b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 3146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 3147b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 3148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 3149b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 3150b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 3151b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3152b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 3153b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3154b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3155efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 3156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 3157b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 3158b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 3159b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 3160b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 3161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 3162219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 3163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 31648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 3165b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 3166b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 3167b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 3168b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 3169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3170b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3171b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 3172b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 3173b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 3174b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3175b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3176b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 317720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3178b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 3179b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 3180b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 3181b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 3182b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 3183b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 3184b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 3185b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 3186b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3187b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 3188b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 3189b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3190b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 3191b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3192b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3193b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 3194b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 3195b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 3196b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 3197b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 3198b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 3199b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 3200b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3201b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3202b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3203b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 3204b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 3205b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3206b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 3207b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 3208b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3209b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3210b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3211b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 3212b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 3213b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 3215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 3216b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3218b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 3220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 3221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3224efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 3225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 3226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 3227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 3229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 3230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 3231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 3232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 3233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 3234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 3235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 3236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 3237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 3238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // language code 3239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3243b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 3244b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 3245b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 3246b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 3247b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3248b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 3249b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 3250b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 3251b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3252b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3253b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3254b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 3255b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 3256b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 3257b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 3258b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 3259b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 3260b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3261b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3262b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 3263b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 3264b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3265b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 3266b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 3267b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 3268b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3269b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3270b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 3271b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 3272b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 3273b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 3274b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3275b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3276b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 3277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 327843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mCodecSpecificDataSize, 5); 3279b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 3281b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 3282b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 3283b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 3284b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 3285b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3286b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 3287b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3288b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 32899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 32909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimvoid MPEG4Writer::Track::writeHvccBox() { 32919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim CHECK(mCodecSpecificData); 32929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim CHECK_GE(mCodecSpecificDataSize, 5); 32939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 32949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // Patch avcc's lengthSize field to match the number 32959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim // of bytes we use to indicate the size of a nal unit. 32969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim uint8_t *ptr = (uint8_t *)mCodecSpecificData; 32979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 32989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->beginBox("hvcC"); 32999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 33009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim mOwner->endBox(); // hvcC 33019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim} 33029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim 3303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 3304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 3305b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 3306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3307b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 3308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 3309b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 3310b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3311b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3312b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 3313b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 3314b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 3315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 3316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 3317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 3318b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3319b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3320000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 3321a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 3322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 332443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 3325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3327000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 3328000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 3329000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3330000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 3331000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 3332000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3333c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3334c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mSttsTableEntries->get(duration, 1)); 3335c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back to host byte order 3336c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 3337c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 3338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 3339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 334020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3341965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 3342965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { // ctts is not for audio 3343965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3344965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3345965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3346000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 3347000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 3348000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 3349000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 3350000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3351965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 3352c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 3353965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3354965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3355965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3356a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]", 3357c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 3358965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3359965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 3360000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3361c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3362c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCttsTableEntries->get(duration, 1)); 3363c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back host byte order 3364c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1); 3365c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 3366965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 3367965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 3368965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 3370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 3371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3372c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 3373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 3374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 337525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 3376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 3377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 3378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3379c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 3380c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 3381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 3382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 338320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 3385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 3386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3387c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 3388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 3389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 339020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 3392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 3393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3394c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 3395c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 3396c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 3397c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 3398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 340020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 340120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 340207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 340307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 340407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 340507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 340607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 340707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 3408e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() { 3409e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("hdlr"); 3410e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3411e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Predefined 3412e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3413e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[0] 3414e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[1] 3415e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[2] 3416e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt8(0); // Name (empty) 3417e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3418e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3419e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3420e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() { 3421e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3422e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3423e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("keys"); 3424e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3425e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(count); // Entry_count 3426e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3427e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3428e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3429e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t n = strlen(key); 3430e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(n + 8); 3431e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3432e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang write(key, n); // write without the \0 3433e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3434e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3435e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3436e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3437e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() { 3438e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3439e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3440e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("ilst"); 3441e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3442e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox(i + 1); // key id (1-based) 3443e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("data"); 3444e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3445e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3446e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang switch (type) { 34477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang case AMessage::kTypeString: 34487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang { 34497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang AString val; 34507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang CHECK(mMetaKeys->findString(key, &val)); 34517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(1); // type = UTF8 34527c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 34537c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang write(val.c_str(), strlen(val.c_str())); // write without \0 34547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang break; 34557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 34567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 3457e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeFloat: 3458e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3459e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang float val; 3460e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findFloat(key, &val)); 34617c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(23); // type = float32 34627c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3463e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(*reinterpret_cast<int32_t *>(&val)); 3464e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3465e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3466e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3467e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeInt32: 3468e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3469e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang int32_t val; 3470e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findInt32(key, &val)); 34717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(67); // type = signed int32 34727c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3473e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(val); 3474e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3475e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3476e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3477e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang default: 3478e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3479e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang ALOGW("Unsupported key type, writing 0 instead"); 34807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(77); // type = unsigned int32 34817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3482e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 3483e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3484e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3485e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3486e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // data 3487e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // key id 3488e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3489e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // ilst 3490e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3491e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3492e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() { 3493e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3494e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (count == 0) { 3495e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return; 3496e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3497e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3498e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("meta"); 3499e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeHdlr(); 3500e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeKeys(); 3501e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeIlst(); 3502e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3503e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3504e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 350507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 350607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 350707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 350807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 350907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 351007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 351107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 351207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 351307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 3514432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 3515432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 351607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 351707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 351807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 351907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 352007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 352107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 352207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 352307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 352420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3525