MPEG4Writer.cpp revision e502b443ce9d229d1e9108834887c6e520948816
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> 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 3618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 3703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h> 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 40d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h> 4107ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h> 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h" 4419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 45dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn 46dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false 47dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0) 48dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif 49dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn 5011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \ 51dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \ 5211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih ALOGW("Condition %s failed " message, #condition, ##__VA_ARGS__); \ 5311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih true; \ 5411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih})) 5511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5877e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024; 591f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32 601f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad // filesystem file size 611f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad // used by most SD cards 623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07; 633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08; 6470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs = 700000LL; 655b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong 667c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[] = "com.android.version"; 673b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#ifdef SHOW_MODEL_BUILD 683b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnarstatic const char kMetaKey_Model[] = "com.android.model"; 697c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[] = "com.android.build"; 703b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar#endif 717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps"; 727c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang/* uncomment to include model and build in meta */ 747c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1 757c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 78bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId); 798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 8337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t stop(); 8437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 8525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 873b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 88d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 89b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTrackHeader(bool use32BitOffset = true); 901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 94c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong void addChunkOffset(off64_t offset); 9570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int32_t getTrackId() const { return mTrackId; } 96dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 978b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan static const char *getFourCCForMime(const char *mime); 9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 100000e18370baae60ffd9f25b509501dd8c26deabfJames Dong enum { 101000e18370baae60ffd9f25b509501dd8c26deabfJames Dong kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 1028c460498c028888c533ab442be12b6d4b669b965James Dong kSampleArraySize = 1000, 103000e18370baae60ffd9f25b509501dd8c26deabfJames Dong }; 104000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // A helper class to handle faster write box with table entries 106c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong template<class TYPE> 107c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong struct ListTableEntries { 108c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity) 109c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mElementCapacity(elementCapacity), 110c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEntryCapacity(entryCapacity), 111c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTotalNumTableEntries(0), 112c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry(0), 113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement(NULL) { 114c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mElementCapacity, 0); 115c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mEntryCapacity, 0); 116c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 117c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Free the allocated memory. 119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ~ListTableEntries() { 120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (!mTableEntryList.empty()) { 121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete[] (*it); 123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.erase(it); 124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Replace the value at the given position by the given value. 128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // There must be an existing value at the given position. 129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order 130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void set(const TYPE& value, uint32_t pos) { 13225f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity); 133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value; 144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Get the value at the given position by the given value. 147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value the retrieved value at the position in network byte order. 148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @return true if a value is found. 150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool get(TYPE& value, uint32_t pos) const { 15125f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong if (pos >= mTotalNumTableEntries * mEntryCapacity) { 152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return false; 153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong value = (*it)[(pos % (mElementCapacity * mEntryCapacity))]; 165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return true; 166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Store a single value. 169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order. 170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void add(const TYPE& value) { 171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nValues = mNumValuesInCurrEntry % mEntryCapacity; 174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries == 0 && nValues == 0) { 175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity]; 176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCurrTableEntriesElement != NULL); 177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.push_back(mCurrTableEntriesElement); 178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t pos = nEntries * mEntryCapacity + nValues; 181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement[pos] = value; 182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mNumValuesInCurrEntry; 184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) { 185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mTotalNumTableEntries; 186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry = 0; 187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Write out the table entries: 191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 1. the number of entries goes first 192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 2. followed by the values in the table enties in order 193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg writer the writer to actual write to the storage 194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void write(MPEG4Writer *writer) const { 195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0); 196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries; 197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->writeInt32(nEntries); 198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong it != mTableEntryList.end(); ++it) { 200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(nEntries, 0); 201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries >= mElementCapacity) { 202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity); 203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong nEntries -= mElementCapacity; 204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries); 206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong break; 207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Return the number of entries in the table. 212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count() const { return mTotalNumTableEntries; } 213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong private: 215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mElementCapacity; // # entries in an element 216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mEntryCapacity; // # of values in each entry 217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mTotalNumTableEntries; 218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mNumValuesInCurrEntry; // up to mEntryCapacity 219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong TYPE *mCurrTableEntriesElement; 220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mutable List<TYPE *> mTableEntryList; 221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong }; 224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 229693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 231a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 232a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 233eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 2341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 2351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 2361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 237bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 238c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 23943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 240e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 241d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 2421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 2438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 247be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 24813aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 2491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool mSamplesHaveSameSize; 251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStszTableEntries; 252be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStcoTableEntries; 254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<off64_t> *mCo64TableEntries; 255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStscTableEntries; 256c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStssTableEntries; 257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mSttsTableEntries; 258c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mCttsTableEntries; 259965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 260000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMinCttsOffsetTimeUs; 261000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMaxCttsOffsetTimeUs; 262965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 2643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 2653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 2663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 2673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 2683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 2693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 2703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 2713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 2723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 2733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 2743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 2753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 2763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 279548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 28093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 28225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 2833c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 28470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 28570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 28693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 28793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 28825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 289872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 290872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 291872a481558350634a3fd5cb67939de288af00ecbJames Dong 292000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int32_t getStartTimeOffsetScaledTime() const; 293000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 29537187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 2983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 2993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 303215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 304215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 305faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 30693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 30703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 30819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 30919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 310c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 311c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 312c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 313c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 314c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 315c059860c73678a202bfa33062723e8f82fb779d9James Dong 316690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 317690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 31813f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t mRotation; 319690f546b0ee548dbfe997df36418e5302ec2d786James Dong 3201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 3211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 3221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 32379761ab096f57c3027fad9556c2bc436672d614eJames Dong 32479761ab096f57c3027fad9556c2bc436672d614eJames Dong // Duration is time scale based 32579761ab096f57c3027fad9556c2bc436672d614eJames Dong void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 326965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 32745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 32845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong bool isTrackMalFormed() const; 32943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 3301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 337965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void writeCttsBox(); 338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 345efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeMdhdBox(uint32_t now); 346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 349efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeTkhdBox(uint32_t now); 350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36030ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 361674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(dup(fd)), 362674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(mFd < 0? NO_INIT: OK), 363de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording(true), 364b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 3651acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 366a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 367a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 368a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 369411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 37030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 37113aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 372e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mMoovBoxBuffer(NULL), 373e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mMoovBoxBufferOffset(0), 374e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mWriteMoovBoxToMemory(false), 375e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mFreeBoxOffset(0), 376e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mStreamableFile(false), 3777837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 3787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize(0), 37907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 380e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mTimeScale(-1), 381e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mStartTimestampUs(-1ll), 38207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 38307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 38486b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 385ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar mStartTimeOffsetMs(-1), 386ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar mMetaKeys(new AMessage()) { 3877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang addDeviceMeta(); 38830ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 38930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 39020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 3918bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong reset(); 39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 3941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 3961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 3971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 402dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 403dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 404dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 405dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 406dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 407dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 408dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 409dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 410dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 411dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 412dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 413dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 414dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 415dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 416dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 417dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 418dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 419dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 42084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber int fd, const Vector<String16>& /* args */) const { 421dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 422dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 423dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 424dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 425dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 426dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 427dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 428dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 429c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 43013210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 431377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); 43213210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 433dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 434dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 435dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 436dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 4378b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static 4388b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) { 4398b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (mime == NULL) { 4408b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 4418b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 4428b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strncasecmp(mime, "audio/", 6)) { 4438b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 4448b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "samr"; 4458b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 4468b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "sawb"; 4478b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 4488b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4a"; 4498b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 4508b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strncasecmp(mime, "video/", 6)) { 4518b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 4528b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4v"; 4538b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 4548b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "s263"; 4558b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 4568b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "avc1"; 4578b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 4588b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else { 4598b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan ALOGE("Track (%s) other than video or audio is not supported", mime); 4608b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 4618b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 4628b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan} 4638b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan 4642dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 465bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 466bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 46729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Attempt to add source AFTER recording is started"); 468bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 469bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 470acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 471acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // At most 2 tracks can be supported. 472acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.size() >= 2) { 473a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGE("Too many tracks (%zu) to add", mTracks.size()); 474acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 475acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 476acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 477acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong CHECK(source.get() != NULL); 478acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 479acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong const char *mime; 480acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong source->getFormat()->findCString(kKeyMIMEType, &mime); 481acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong bool isAudio = !strncasecmp(mime, "audio/", 6); 4828b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (Track::getFourCCForMime(mime) == NULL) { 4838b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan ALOGE("Unsupported mime '%s'", mime); 484acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 485acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 486acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 487acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // At this point, we know the track to be added is either 488acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // video or audio. Thus, we only need to check whether it 489acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // is an audio track or not (if it is not, then it must be 490acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // a video track). 491acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 492acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // No more than one video or one audio track is supported. 493acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong for (List<Track*>::iterator it = mTracks.begin(); 494acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong it != mTracks.end(); ++it) { 495acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if ((*it)->isAudio() == isAudio) { 496acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("%s track already exists", isAudio? "Audio": "Video"); 497acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 498acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 499acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 500acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 501acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // This is the first track of either audio or video. 502acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // Go ahead to add the track. 503219f195159f93d627af2b243732e3f9020511a46James Dong Track *track = new Track(this, source, 1 + mTracks.size()); 50420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 5052dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 5062dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 50993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 510acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.empty()) { 511acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("No source added"); 512acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return INVALID_OPERATION; 513acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 514acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 515a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 516a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 51793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 518a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 519a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 520a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 521a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 522a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 523a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 524a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 525a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 526a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 527a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 528a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 529a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 530a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 5317c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() { 5327c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // add device info and estimate space in 'moov' 5337c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang char val[PROPERTY_VALUE_MAX]; 5347c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size_t n; 5357c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // meta size is estimated by adding up the following: 5367c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - meta header structures, which occur only once (total 66 bytes) 5377c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - size for each key, which consists of a fixed header (32 bytes), 5387c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // plus key length and data length. 5397c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 66; 5407c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.version.release", val, NULL) 5417c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 5427c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Version, val, n + 1); 5437c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32; 5447c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 5457c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD 5467c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.product.model", val, NULL) 5477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 5487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Model, val, n + 1); 5497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32; 5507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 5517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.display.id", val, NULL) 5527c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 5537c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Build, val, n + 1); 5547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32; 5557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 5567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif 5577c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang} 5587c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 5592dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 5602dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 5612dec2b5be2056c6d9428897dc672185872d30d17James Dong // 5622dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 5632dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 5642dec2b5be2056c6d9428897dc672185872d30d17James Dong 56578a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 5662dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 56778a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 5682dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 5692dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 5702dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 5712dec2b5be2056c6d9428897dc672185872d30d17James Dong 5722dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 5732dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 5742dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 57578a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 5762dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 5772dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 5782dec2b5be2056c6d9428897dc672185872d30d17James Dong 57978a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 580a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 58178a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 58278a1a286f736888ae7af8860b2c424af0d978848James Dong } 58378a1a286f736888ae7af8860b2c424af0d978848James Dong 58478a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 58578a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 58678a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 58778a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 58878a1a286f736888ae7af8860b2c424af0d978848James Dong ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000); 58978a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 59078a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 59178a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 59278a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 59378a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 59478a1a286f736888ae7af8860b2c424af0d978848James Dong } 59578a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 59678a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 59778a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 59878a1a286f736888ae7af8860b2c424af0d978848James Dong } 5992dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6002dec2b5be2056c6d9428897dc672185872d30d17James Dong } 60178a1a286f736888ae7af8860b2c424af0d978848James Dong 6022dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 6032dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 6042dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6052dec2b5be2056c6d9428897dc672185872d30d17James Dong 6062dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 6072dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 6082dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 6092dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 6102dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6112dec2b5be2056c6d9428897dc672185872d30d17James Dong 6127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // Account for the extra stuff (Geo, meta keys, etc.) 6137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size += mMoovExtraSize; 6147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 615a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the" 616a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn " estimated moov size %" PRId64 " bytes", 6172dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 6182dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 6192dec2b5be2056c6d9428897dc672185872d30d17James Dong} 6202dec2b5be2056c6d9428897dc672185872d30d17James Dong 6212dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 622674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 62325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 626a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 627a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 628a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 629a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 630a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 631a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 632a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 633a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 634a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 635a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 6362dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 6372dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 6382dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 6392dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 6402dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 6412dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6422dec2b5be2056c6d9428897dc672185872d30d17James Dong 6431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 6441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 6451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 6461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 6471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 6491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 6501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 6511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 652a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. " 653a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn "It is changed to %" PRId64 " bytes", 654d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 655d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 6561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 659b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 660b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 661b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 662b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 663b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 6642dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6652dec2b5be2056c6d9428897dc672185872d30d17James Dong 666de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui int32_t isRealTimeRecording; 667de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) { 668de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording = isRealTimeRecording; 669de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 670de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 671065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 67293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 673a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 674a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 675a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 67693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 677a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 678a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 679a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 680a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 6818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 6828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 6838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 6848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 68543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 6863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("movie time scale: %d", mTimeScale); 6878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 68877e8ae9967a078770416619e99ddb5b010def312James Dong /* 68977e8ae9967a078770416619e99ddb5b010def312James Dong * When the requested file size limit is small, the priority 69077e8ae9967a078770416619e99ddb5b010def312James Dong * is to meet the file size limit requirement, rather than 6917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to make the file streamable. mStreamableFile does not tell 6927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * whether the actual recorded file is streamable or not. 69377e8ae9967a078770416619e99ddb5b010def312James Dong */ 69477e8ae9967a078770416619e99ddb5b010def312James Dong mStreamableFile = 69577e8ae9967a078770416619e99ddb5b010def312James Dong (mMaxFileSizeLimitBytes != 0 && 69677e8ae9967a078770416619e99ddb5b010def312James Dong mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 69777e8ae9967a078770416619e99ddb5b010def312James Dong 6987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong /* 6997b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory is true if the amount of data in moov box is 7007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * smaller than the reserved free space at the beginning of a file, AND 7017b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * when the content of moov box is constructed. Note that video/audio 7027b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * frame data is always written to the file but not in the memory. 7037b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Before stop()/reset() is called, mWriteMoovBoxToMemory is always 7057b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * false. When reset() is called at the end of a recording session, 7067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Moov box needs to be constructed. 7077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory 7097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to set to mStreamableFile so that if 7107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the file is intended to be streamable, it is set to true; 7117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * otherwise, it is set to false. When the value is set to false, 7127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * all the content of the moov box is written immediately to 7137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the end of the file. When the value is set to true, all the 7147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * content of the moov box is written to an in-memory cache, 7157b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mMoovBoxBuffer, util the following condition happens. Note 7167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * that the size of the in-memory cache is the same as the 7177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * reserved free space at the beginning of the file. 7187b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 2) While the data of the moov box is written to an in-memory 7207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache, the data size is checked against the reserved space. 7217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * If the data size surpasses the reserved space, subsequent moov 7227b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * data could no longer be hold in the in-memory cache. This also 7237b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * indicates that the reserved space was too small. At this point, 7247b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * _all_ moov data must be written to the end of the file. 7257b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory must be set to false to direct the write 7267b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to the file. 7277b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 3) If the data size in moov box is smaller than the reserved 7297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space after moov box is completely constructed, the in-memory 7307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache copy of the moov box is written to the reserved free 7317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space. Thus, immediately after the moov is completedly 7327b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * constructed, mWriteMoovBoxToMemory is always set to false. 7337b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong */ 7347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 7357837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 7367837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 7377837c17063a4c50bc856ba59418516fdab731de7James Dong 738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7407837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7427837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 7432dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 7442dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 7452dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 7462dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7472dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 7487837c17063a4c50bc856ba59418516fdab731de7James Dong } 74943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mEstimatedMoovBoxSize, 8); 75077e8ae9967a078770416619e99ddb5b010def312James Dong if (mStreamableFile) { 75177e8ae9967a078770416619e99ddb5b010def312James Dong // Reserve a 'free' box only for streamable file 75277e8ae9967a078770416619e99ddb5b010def312James Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 75377e8ae9967a078770416619e99ddb5b010def312James Dong writeInt32(mEstimatedMoovBoxSize); 75477e8ae9967a078770416619e99ddb5b010def312James Dong write("free", 4); 75577e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 75677e8ae9967a078770416619e99ddb5b010def312James Dong } else { 75777e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mOffset; 75877e8ae9967a078770416619e99ddb5b010def312James Dong } 7597837c17063a4c50bc856ba59418516fdab731de7James Dong 7607837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 761c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 7621acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 7631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 7641acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 7651acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 7661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 7671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 7691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 7701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 7711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 7721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 774a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 775a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 7771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 778a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 77925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 7831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 7841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 7851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 78637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 787674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 78837187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 789a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 790a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 79137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 792a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 793a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 79437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 79537187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 79637187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 79737187916a486504acaf83bea30147eb5fbf46ae5James Dong } 798a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 79937187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 800a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 801a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 8021c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 803b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping writer thread"); 804411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 805411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 806411ba422e3635d534928ffd81abf54f4f291c739James Dong } 8071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 8091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 8101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 8121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 8131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 8161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 817411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 818b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Writer thread stopped"); 8191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 8201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 82113f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 82213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 82313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 82413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 82513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 82613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 82713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 82813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 82913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 83013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 83113f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 83213f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 8333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeCompositionMatrix"); 83413f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 83513f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 83613f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 83713f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 83813f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 83913f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 84013f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 84113f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 84213f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 84313f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 84413f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 84513f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 84613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 84713f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 84813f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 84913f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 85013f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 85113f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 85213f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 85313f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 85413f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 85513f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 85613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 85713f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 85813f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 85913f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 86013f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 86113f6284305e4b27395a23db7882d670bdb1bcae1James Dong 86213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 86313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 86413f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 86513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 86613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 86713f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 86813f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 86913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 87013f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 87113f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 87213f6284305e4b27395a23db7882d670bdb1bcae1James Dong 873411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 874411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 875411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 876411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 877411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 8784c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary free(mMoovBoxBuffer); 8794c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary mMoovBoxBuffer = NULL; 880411ba422e3635d534928ffd81abf54f4f291c739James Dong} 88113f6284305e4b27395a23db7882d670bdb1bcae1James Dong 8828bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() { 883674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 88437187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 885411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 886411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 887411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 888411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 889411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 890411ba422e3635d534928ffd81abf54f4f291c739James Dong } 891411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 892411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 893411ba422e3635d534928ffd81abf54f4f291c739James Dong } 89420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 89520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 89637187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 8978f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 89865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 90020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 90137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 90237187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 90337187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 90437187916a486504acaf83bea30147eb5fbf46ae5James Dong } 90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 9078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 9088f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 91065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 91165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 91265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 91365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 91465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 91565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 916a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us", 91765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 9217837c17063a4c50bc856ba59418516fdab731de7James Dong 92237187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 92337187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 924411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 92537187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 92637187916a486504acaf83bea30147eb5fbf46ae5James Dong } 92737187916a486504acaf83bea30147eb5fbf46ae5James Dong 92820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 9291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 930c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 9311f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); 932c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 9331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 934c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 9351f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint64_t size = mOffset - mMdatOffset; 9361acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 937c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 9381acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 939c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Construct moov box now 9427837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 9437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = mStreamableFile; 9447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 9457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // There is no need to allocate in-memory cache 9467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // for moov box if the file is not streamable. 9477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 9487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 9497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong CHECK(mMoovBoxBuffer != NULL); 9507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // mWriteMoovBoxToMemory could be set to false in 9547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // MPEG4Writer::write() method 9557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 9567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 9577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Content of the moov box is saved in the cache, and the in-memory 9587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // moov box needs to be written to the file in a single shot. 9597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 96043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 9617837c17063a4c50bc856ba59418516fdab731de7James Dong 9627837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 963c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 9647837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 965674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 9667837c17063a4c50bc856ba59418516fdab731de7James Dong 9677837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 968c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 9697837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 9707837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 9717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } else { 9727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ALOGI("The mp4 file will not be streamable."); 9737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 9747837c17063a4c50bc856ba59418516fdab731de7James Dong 9757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Free in-memory cache for moov box 9767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mMoovBoxBuffer != NULL) { 9777837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 9787837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 9797837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 9807837c17063a4c50bc856ba59418516fdab731de7James Dong } 9817837c17063a4c50bc856ba59418516fdab731de7James Dong 9820c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 984411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 98537187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 988efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() { 989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 990efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 991efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // while time function returns Unix epoch values which starts 992efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // at 1970-01-01. Lets add the number of seconds between them 993efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60); 994efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson return mpeg4Time; 995efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson} 996efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson 997efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 998efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 1000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 1001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 1002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 1003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 1004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 1005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 1006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 1007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 1008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 1009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 1012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 1019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 1020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 1023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 1024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 102507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 102607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 102707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 1028e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeMetaBox(); 1029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 1030b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 1031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 1032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 1033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 1035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 10372cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 1038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 1039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 1041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 1042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 1043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 10448284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 10458284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("isom"); 10468284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("3gp4"); 1047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 10488284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 10498284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 1050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 10518284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 1052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 1055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 105707ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 105807ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 105907ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 106007ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 106107ec01904613a0bac32caaa8444b4690998faed7James Dong 106207ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 106307ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 106407ec01904613a0bac32caaa8444b4690998faed7James Dong char value[PROPERTY_VALUE_MAX]; 106507ec01904613a0bac32caaa8444b4690998faed7James Dong if (property_get("rw.media.record.test", value, NULL) && 106607ec01904613a0bac32caaa8444b4690998faed7James Dong (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 106707ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 106807ec01904613a0bac32caaa8444b4690998faed7James Dong } 106907ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 107007ec01904613a0bac32caaa8444b4690998faed7James Dong} 107107ec01904613a0bac32caaa8444b4690998faed7James Dong 107270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 107307ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 107407ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 107507ec01904613a0bac32caaa8444b4690998faed7James Dong return; 107607ec01904613a0bac32caaa8444b4690998faed7James Dong } 107707ec01904613a0bac32caaa8444b4690998faed7James Dong 107870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 107970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 108070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 108170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 108270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 108370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 108470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 108570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 108670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 108713aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 108813aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 108913aec890216948b0c364f8f92792129d0335f506James Dong return OK; 109013aec890216948b0c364f8f92792129d0335f506James Dong} 109113aec890216948b0c364f8f92792129d0335f506James Dong 109213aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 109313aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 109413aec890216948b0c364f8f92792129d0335f506James Dong} 109513aec890216948b0c364f8f92792129d0335f506James Dong 109613aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 109713aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 109813aec890216948b0c364f8f92792129d0335f506James Dong} 109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1100c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 1101c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1103c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1104c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1105c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 111203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 111303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 111403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 111503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 111603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 111703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 111803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 111903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 112003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 112103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 112203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 112303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 112403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 112503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1126c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 1127c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 112830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 112930ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 113003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1131b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 1132b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 1133c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1134b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 1135c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1136b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 1137c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1138b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1139c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1140c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 1141c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1142c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1143c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 1144b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1145b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 1146b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 114743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(length, 65536); 114830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1149b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 1150c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1151b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1152c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1153c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1154b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 1155b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 115630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 115730ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 115830ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 115930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 11607837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 1161674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 11627837c17063a4c50bc856ba59418516fdab731de7James Dong 11637837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 11647837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 11657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 1166c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 11671acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 11687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // The reserved moov box at the beginning of the file 11697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // is not big enough. Moov box should be written to 11707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the end of the file from now on, but not to the 11717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // in-memory cache. 11727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 11737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // We write partial moov box that is in the memory to 11747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the file first. 1175c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 11767837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 11777837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 11787837c17063a4c50bc856ba59418516fdab731de7James Dong } 1179674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 1180674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 11817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ::write(mFd, ptr, bytes); 11827837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 11837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 11847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // All subsequent moov box content will be written 11857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // to the end of the file. 11867837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 11877837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 11887837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 11897837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 11907837c17063a4c50bc856ba59418516fdab731de7James Dong } 11917837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1192674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 11937837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 11947837c17063a4c50bc856ba59418516fdab731de7James Dong } 11957837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 11967837c17063a4c50bc856ba59418516fdab731de7James Dong} 11977837c17063a4c50bc856ba59418516fdab731de7James Dong 1198e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) { 1199e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mBoxes.push_back(mWriteMoovBoxToMemory? 1200e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mMoovBoxBufferOffset: mOffset); 1201e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 1202e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 1203e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(id); 1204e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1205e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 12070c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12097837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 12107837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 12170c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1219c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12227837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 12237837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 12247837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 12257837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1226c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 12277837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 12287837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1229c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 12307837c17063a4c50bc856ba59418516fdab731de7James Dong } 123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1234674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1239674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 124220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 124320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1244674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1249674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1254674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 12580c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 1259674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 126207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 126307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 126407b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 126507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 126607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 126707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 126807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 126907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 127007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 127107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 127207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 127307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 127407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 127507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 127607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 127707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 127807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 127907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 128007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 128107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 128207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 128307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 128407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 128507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 128607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 128707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 128807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 128907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 129007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 129107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 129207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 129307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 129407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 129507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 129607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 129707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 129807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 129907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 130007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 130107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 130207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 130307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 130407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 130507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 130607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 130707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 130807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 130907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 131007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 131107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 131207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 131307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 131407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 131507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 131607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 131707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 131807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 131907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 132007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 132107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 132207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 132307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 132407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 132507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 132607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 132707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 132807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 132907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 13307c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 30; 133107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 133207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 133307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 1334e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) { 1335e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (captureFps <= 0.0f) { 1336e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return BAD_VALUE; 1337e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 1338e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 13397c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps); 13407c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32; 13417c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 1342e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return OK; 1343e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1344e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1346674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134978a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 135078a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 135178a1a286f736888ae7af8860b2c424af0d978848James Dong} 135278a1a286f736888ae7af8860b2c424af0d978848James Dong 1353d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1354d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1355d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1356d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1357d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1358d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1359956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1360d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1361d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1362d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1363d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 13641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 136577e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 136677e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 136777e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 136877e8ae9967a078770416619e99ddb5b010def312James Dong } 1369acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1370acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1371acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1372acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1373d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1374d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1375d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1376d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1377d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1378d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1379d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1380d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1381d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1382d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1383d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1384d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1385d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1386d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1387d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1388d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1389d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 139025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 139125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 139225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 139325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 139425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 139525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 139625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 139725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 139825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 139925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 140025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 140125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 140225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1403f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1404a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("setStartTimestampUs: %" PRId64, timeUs); 140543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 14063c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1407065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1408f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1409a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs); 14103c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 14113c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 14123c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1413f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 14143c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 14153c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 14163c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 14173c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 141858ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 141958ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 142058ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 142158ae9c530247668f8af36e30d228c716c226b3d4James Dong} 142258ae9c530247668f8af36e30d228c716c226b3d4James Dong 142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 142420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 142520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1426bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 142825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1431a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1432a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1433eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1434bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1435c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1436956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1437be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1438c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1439c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1440c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)), 1441c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)), 1442c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1443c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 1444c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 144625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1447548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 144813f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 144913f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 145019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 14518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 14521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 14531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 14541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 14551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 14561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 14571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 14581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1459c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1460c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1461c059860c73678a202bfa33062723e8f82fb779d9James Dong 14621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 14631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1464c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1465c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 1466c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 1467c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1468c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 14691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 147078a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 147178a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 147278a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 147378a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1474c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1475c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1476c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1477c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 147878a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 147978a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 148078a1a286f736888ae7af8860b2c424af0d978848James Dong } 14811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 14841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 14851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1486c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(chunkId)); 1487c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(sampleId)); 1488c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(1)); 14891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1492c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 14931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 149679761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 14971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14985a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 1499377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGW("0-duration samples found: %zu", sampleCount); 15005a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1501c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1502c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 15031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 15041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1505965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1506965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1507965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1508965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { 1509965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1510965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1511c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1512c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1513965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1514965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1515c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1516c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1517c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1518c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1519c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1520c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1521c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 15221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 15231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1524c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 15253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 1526c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1527c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1528c059860c73678a202bfa33062723e8f82fb779d9James Dong 1529c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1530c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1531c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1532c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1533c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1534c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1535c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1536c059860c73678a202bfa33062723e8f82fb779d9James Dong 1537c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1538c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1539c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1540c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1541c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1542c059860c73678a202bfa33062723e8f82fb779d9James Dong 154343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 154419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 154519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 154619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 154719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 154819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 154919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 155019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 155119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 155219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 155319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 155419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 155519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 155619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 155719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 155819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 155919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 156019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 156119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 156219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 156319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 156419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 156519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 156619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 156719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 156819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 156919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 157019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 157119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 157219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 157319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 157419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 157520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 157620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 157720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 157820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 157920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1580c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 1581c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 1582c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 1583c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 1584c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 1585c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 1586c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 1587c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 1588c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 1589c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 1590c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 1591c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 1592c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 1593c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 1594c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 1595c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 159620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 159720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 159820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 159920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 160020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 160120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 160293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 16033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 160493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 160593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 160693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 160793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 160893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 160993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 1610a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs); 161193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 161293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 161393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 161493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 161593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 161693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 16171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 16181c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 16193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 16201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 16211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 16221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 16231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16251c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 16263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 16271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 16281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 16291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 16311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 16321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 16341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 16351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 16361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 16371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 164043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 16411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1643fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1644a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("writeChunkToFile: %" PRId64 " from %s track", 16455410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video"); 1646fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1647fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1648fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1649fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1650fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1651fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong off64_t offset = chunk->mTrack->isAvc() 1652fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong ? addLengthPrefixedSample_l(*it) 1653fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1654fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1655fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1656fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1657fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 16581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 16611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1662fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 16631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1664fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 16651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1667fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 16683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 16691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 167070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 167170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1672e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 167370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 16741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 167570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 167670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 167770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 16781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 1679377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGD("%zu chunks are written in the last batch", outstandingChunks); 16801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1682fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 16833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 16841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 16861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 16871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 16881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 16891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 16901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 16911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 16921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 16931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 16941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 16993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 1700fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 17011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 17041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 17051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1706fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 17071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 17081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 17091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1710fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1711fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1712fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 171370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 171470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 171570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 171670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 171770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 171870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 171970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1720fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 17211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1723fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1724fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 17251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17271c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 17283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 17291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1730a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1731fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1732fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 17331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1734fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1735fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1736fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1737fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 17381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 17391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1741de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // In real time recording mode, write without holding the lock in order 1742de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // to reduce the blocking time for media track threads. 1743de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // Otherwise, hold the lock until the existing chunks get written to the 1744de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // file. 1745fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 1746de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1747de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.unlock(); 1748de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1749fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 1750de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1751de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.lock(); 1752de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1753fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 17541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1755fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1756fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 17571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17591c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 17603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 17611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 17631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1764e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 17651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 17661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 17671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 17681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 176970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 177070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 17711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 17721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 17751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 17761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 17771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 17781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 1779411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 17801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 17811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 178493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1785a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1786a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1787a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1788a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1789a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 179025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 179193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 179219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 179319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 179419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 179570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 179619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 179713f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 179813f6284305e4b27395a23db7882d670bdb1bcae1James Dong if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 179913f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 180013f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 180113f6284305e4b27395a23db7882d670bdb1bcae1James Dong 180293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 180393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1804f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1805de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 1806a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 1807a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 1808a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 1809a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 1810a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 1811a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 181286b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 181386b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 1814a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 181586b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 181686b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 181786b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 181886b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 181986b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 1820a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs); 1821a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 1822a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1823f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1824a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1825f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 182625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 182725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 182825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 182925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 183020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 183120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 183220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 183320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 183420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 183520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1836eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 1837c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 183825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1839956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 18401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 184143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 184220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 184325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 184420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 184525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 184625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 184720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 184937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1850a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 185137187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1852a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1853a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 185437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 185572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track stopping", mIsAudio? "Audio": "Video"); 1856eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 185729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 1858eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 1859eaae38445a340c4857c1c5569475879a728e63b7James Dong } 1860eaae38445a340c4857c1c5569475879a728e63b7James Dong 186120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 186237187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 186320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 186420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 186520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 186672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track source stopping", mIsAudio? "Audio": "Video"); 186772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mSource->stop(); 186872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track source stopped", mIsAudio? "Audio": "Video"); 186972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 187020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 187120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 1872377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 187337187916a486504acaf83bea30147eb5fbf46ae5James Dong 1874b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%s track stopped", mIsAudio? "Audio": "Video"); 187537187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 187620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 187720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 187825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 187925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 188025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 188125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 188220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 188320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 188420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 188520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 188637187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 1887377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT return (void *)(uintptr_t)err; 188820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 188920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 18913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 18923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 18943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 18953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 18983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 18993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 1900a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("findNextStartCode: %p %zu", data, length); 19013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 19033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 19043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 19063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 19083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 19093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 19113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 19123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 19223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 192329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 19253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 19293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 193029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 19363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 19373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 19383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 19393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 19403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 194129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 19423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 19433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 19463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 19473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 19483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 19503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 19513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 19533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 19543856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 19553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 19573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 19583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 1959377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 19603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 19643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 19653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 19663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 19673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 19683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 19703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 19713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 19733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 19743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 19753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 19763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 19773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 19783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 19793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 19803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 19813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 19823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 19833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 19843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 19853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 19863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 19873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 198829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 19893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 19923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 19933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 19953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 19963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 199729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 19983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 20013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 200529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 20063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 20163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 20203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 202329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 20243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 2028377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 20293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 20343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 20353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 20363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 203729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 20383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 2041377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 20423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20451374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 20461374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 20471374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 20481374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 20493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 20503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 20513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 20523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 20533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 205429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 20553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 20563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20581374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 20593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 20603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 2061548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 206203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 206303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 2064548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 206503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 206629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 206703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 206803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 206903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 2071377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 207203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 207303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 207403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 20763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 20773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 207803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 207903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 208103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 208203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 208303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 20853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 208603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 208703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 20883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 20903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 20913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 209203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2094b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2095b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 2096b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2097b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 2098b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 209903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 21003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 21013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 21023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 21033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 21043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 21053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 21063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 21073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 21083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 21093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 21103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 21123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 21133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 21143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 21173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 21183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 21193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 21203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 21213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 21223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 21233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 21243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 21253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 21263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 21283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 21293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 21303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 213103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 213203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 213303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 213403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 2135872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 2136872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 2137872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 2138872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 2139872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 2140872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2141872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 2142872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 2143872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2144872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 2145872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2146872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2147872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2148872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 2149872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2150872a481558350634a3fd5cb67939de288af00ecbJames Dong} 2151872a481558350634a3fd5cb67939de288af00ecbJames Dong 215237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 215330ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 215413aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 215543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 215613aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 215713aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 215813aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 2159965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 2160965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 2161965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 2162965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 2163965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 2164000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 2165a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 2166965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 2167000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 2168000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2169000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 217043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 2172e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2173a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 2174a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 2175a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } else { 2176a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 2177a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 2178de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2179de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2180de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2181de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2182985f838934510983d8a887461e98dca60a6e858fJames Dong 2183d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 218420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 218593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 218620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 218711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih const char *trackName = mIsAudio ? "Audio" : "Video"; 218893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 218920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 219020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 219120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 219213aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 219320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 219420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 219520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2196a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 2197a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 2198a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2199a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2200a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2201a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2202a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2203a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2204a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 220530ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 220630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 220703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 220803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 220903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 2210548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 2211548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 22121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 221303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 221403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 221503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 221603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 221743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_EQ((status_t)OK, err); 22181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 221903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 222003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 222103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 222203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 222303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 222403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 222530ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 222630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 222730ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 222830ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 222930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2230548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 223130ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2232a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2233a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2234d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2235d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2236d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2237d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2238d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2239d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2240d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2241d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2242d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2243d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 22441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 2245e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2246b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 2247b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mIsAvc) { 2248b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2249b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2250b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2251b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2252b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2253b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2254050b28a593350047845a45a14cc5026221ac1620James Dong 2255d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 22561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 22571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 22581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2259d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2260d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2261d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2262d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2263d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2264d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2265d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2266d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2267d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2268050b28a593350047845a45a14cc5026221ac1620James Dong 2269d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2270d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2271d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2272d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2273d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 227570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2276f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2277f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 22788428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 22793c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 228048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2281a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 22828428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 228311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) { 228411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 228511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 228611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 228711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 22888428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 228911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) { 229011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 229111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 229211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 229311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 22948428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2295a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2296a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2297a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2298a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 229911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 230011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 230111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 230211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 230311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2304000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (!mIsAudio) { 2305965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2306965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2307965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2308000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 2309965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 2310965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 2311965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2312965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 2313000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 2314000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 231511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) { 231611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 231711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 231811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 231911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2320965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 2321a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64, 2322000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 2323000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2324000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 2325000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 2326000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 232711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) { 232811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 232911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 233011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 233111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2332c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 233343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 233443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 233543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 233643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 233743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 233843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 233943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 234043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 234143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 234243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 234343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 234443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 234543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 234643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 234743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 2348000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2349000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 2350c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 2351000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2352000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2353000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 2354000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2355000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2356000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2357000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2358000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2359000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2360000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2361965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2362872a481558350634a3fd5cb67939de288af00ecbJames Dong 2363de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2364872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2365872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 2366e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2367e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2368872a481558350634a3fd5cb67939de288af00ecbJames Dong 236911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 237011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 237111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 237211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 237311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2374a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64, 237511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, previousPausedDurationUs); 2376c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2377c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 23783b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 23793b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 23805a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 23815a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 23825a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 23835a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 23845a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 23855a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 23865a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 23875a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2388c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 2389a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGE("timestampUs %" PRId64 " < lastTimestampUs %" PRId64 " for %s track", 239011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih timestampUs, lastTimestampUs, trackName); 239111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2392c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return UNKNOWN_ERROR; 23938c460498c028888c533ab442be12b6d4b669b965James Dong } 23948c460498c028888c533ab442be12b6d4b669b965James Dong 239585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // if the duration is different for this sample, see if it is close enough to the previous 239685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // duration that we can fudge it and use the same value, to avoid filling the stts table 239785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // with lots of near-identical entries. 239885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // "close enough" here means that the current duration needs to be adjusted by less 239985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // than 0.1 milliseconds 240085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { 240185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL 240285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen + (mTimeScale / 2)) / mTimeScale; 240385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (deltaUs > -100 && deltaUs < 100) { 240485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // use previous ticks, and adjust timestamp as if it was actually that number 240585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // of ticks 240685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen currDurationTicks = lastDurationTicks; 240785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen timestampUs += deltaUs; 240885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 240985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 241085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen 2411c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 2412c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 2413c059860c73678a202bfa33062723e8f82fb779d9James Dong 2414a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2415a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2416c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 241779761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2418be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2419be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2420be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2421be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2422965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2423be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2424be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2425c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2426be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2427be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 24288644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2429be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2430a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64, 243111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, lastTimestampUs); 24328644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2433c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 24348644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 243520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2436d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 2437c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 2438d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2439d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 244093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 244193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 244293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 244393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2444faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 244593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 244643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2447c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 244858ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 2449c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2450c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count = (mOwner->use32BitFileOffset() 2451c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 2452c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 2453c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2454c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (count == 0) { 24551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 245658ae9c530247668f8af36e30d228c716c226b3d4James Dong } 245758ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 245858ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 245958ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 246058ae9c530247668f8af36e30d228c716c226b3d4James Dong } 246113aec890216948b0c364f8f92792129d0335f506James Dong 246213aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 246313aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 24641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 24651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 246613aec890216948b0c364f8f92792129d0335f506James Dong } else { 246713aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 246813aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 246913aec890216948b0c364f8f92792129d0335f506James Dong } else { 247043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 247143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 247243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 247343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 247443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 247513aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 247613aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 2477c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 2478c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 2479c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 248013aec890216948b0c364f8f92792129d0335f506James Dong } 24811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 248213aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 248313aec890216948b0c364f8f92792129d0335f506James Dong } 248413aec890216948b0c364f8f92792129d0335f506James Dong } 248513aec890216948b0c364f8f92792129d0335f506James Dong } 248613aec890216948b0c364f8f92792129d0335f506James Dong 248720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 248825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 248945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 2490690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2491f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 249245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2493bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2494be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 249513aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 249643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2497c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(1, mStszTableEntries->count()); 249858ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 24991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 25001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 250113aec890216948b0c364f8f92792129d0335f506James Dong } 250213aec890216948b0c364f8f92792129d0335f506James Dong 2503be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2504be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2505be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2506c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 1) { 25078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 250879761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2509be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2510be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2511be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2512a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2513c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() <= 2) { 251479761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2515a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 251679761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2517a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2518a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 251979761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2520a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2521a472613aec322e25891abf5c77bf3f7e3c244920James Dong 252243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // The last ctts box may not have been written yet, and this 252343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // is to make sure that we write out the last ctts box. 252443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 252543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (cttsSampleCount > 0) { 252643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 252743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 252843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 252943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 2530c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 253125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 253243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 253343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 253443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2535df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 253611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih count, nZeroLengthFrames, mStszTableEntries->count(), trackName); 2537872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2538a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs()); 2539872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2540365a963142093a1cd8efdcea76b5f65096a5b115James Dong 254137187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 254237187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 254337187916a486504acaf83bea30147eb5fbf46ae5James Dong } 254437187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2545365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2546365a963142093a1cd8efdcea76b5f65096a5b115James Dong 254745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 2548c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { // no samples written 254929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 255045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 255145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 255245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2553c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (!mIsAudio && mStssTableEntries->count() == 0) { // no sync frames for video 255429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 255545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 255645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 255745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 255845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 255945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 256045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 256145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 256245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 256345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 256445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 256543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 256607ec01904613a0bac32caaa8444b4690998faed7James Dong 256707ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 256807ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 256907ec01904613a0bac32caaa8444b4690998faed7James Dong return; 257007ec01904613a0bac32caaa8444b4690998faed7James Dong } 257107ec01904613a0bac32caaa8444b4690998faed7James Dong 257243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 257343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 257443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 257543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 257643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mIsAudio? 0: 1); 257743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 257843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 257943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 258043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 258143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 258243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 258343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2584c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 258543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 258686b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 258786b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 258886b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 258986b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 259086b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 259186b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 259286b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 259386b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 259486b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 259586b7f47aa7482424cf8fd248f1315311919be3b0James Dong 259686b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 259770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 259870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 259986b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 260070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 260107ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 260207ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 260307ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 260407ec01904613a0bac32caaa8444b4690998faed7James Dong 260543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 260643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 260743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 260843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 260970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 261070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 261170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 261270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 261370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 261470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 261570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 261670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 261743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 261843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 261943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2620faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 2621a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("trackProgressStatus: %" PRId64 " us", timeUs); 2622c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2623215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 2624215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 2625a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs); 2626bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 262793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 262893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 262993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 263093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2631faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 2632bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 2633faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 2634bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 2635faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2636faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 2637faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 2638faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 2639bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2640bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2641faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2642faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 2643faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2644faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2645faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 2646faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 2647bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2648bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2649faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2650faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 2651faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 2652bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2653bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2654faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 2655faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2656faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 2657faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2658d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 2659a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs); 2660e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2661d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 2662e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2663e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2664e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 2665a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs); 2666e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2667e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 2668e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2669e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2670de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const { 2671de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui return mIsRealTimeRecording; 2672de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui} 2673de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2674b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 2675b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 2676b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 2677b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 26781c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 26793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 26801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 26811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 26821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 268313aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 268420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 268520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26863b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 2687c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 268820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 268920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2690d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2691d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 2692d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 2693d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2694690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 2695690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 2696690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2697690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2698690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2699690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2700690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2701690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 270229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 2703690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2704690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2705690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2706690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2707690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 270829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 2709690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2710690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2711690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2712690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2713690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2714690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 271620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s track time scale: %d", 27181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 27198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 2720efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 2721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 2726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 2751965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong writeCttsBox(); 2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mIsAudio) { 2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 27658b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 27668b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 276729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 27718b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan mOwner->beginBox(fourcc); // video format 2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 2792c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->writeInt8(0); // compressor string length 2793c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->write(" ", 31); 2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 279743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(23 + mCodecSpecificDataSize, 128); 2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 2812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 28158b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 28168b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 281729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 2848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 285043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 285343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(mCodecSpecificDataSize + 23, 128); 2854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 2859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 2860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2863b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 2865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2868ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier int32_t bitRate; 2869ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier bool success = mMeta->findInt32(kKeyBitRate, &bitRate); 2870ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier mOwner->writeInt32(success ? bitRate : 96000); // max bit rate 2871ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier mOwner->writeInt32(success ? bitRate : 96000); // avg bit rate 2872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2881b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 2888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 288943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 2903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 0x77, 0x00, 2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00, 2907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00 2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 2910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2916b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2926efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 2928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 2929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 2930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 2931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2933219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 2934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 29358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 2936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 2937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 2938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 2943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 294820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 2955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 2962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 2965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 2966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 2967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 2968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 2969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 2976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 2978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 2983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 2984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 2986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 2991b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2993b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2995efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 3006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // language code 3010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 3015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 3016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 3017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 3018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 3020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 3021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 3022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3025b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 3026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 3027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 3028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 3029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 3030b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 3031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 3037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 3038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 3039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 3042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 3043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 3044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 3045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 3048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 304943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mCodecSpecificDataSize, 5); 3050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 3052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 3053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 3054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 3058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 3061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 3062b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 3063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 3065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 3067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 3070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 3071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 3073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 3074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 3075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3077000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 3078a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 3079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 308143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 3082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3084000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 3085000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 3086000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3087000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 3088000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 3089000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3090c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3091c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mSttsTableEntries->get(duration, 1)); 3092c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back to host byte order 3093c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 3094c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 3095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 3096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 309720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3098965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 3099965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { // ctts is not for audio 3100965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3101965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3102965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3103000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 3104000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 3105000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 3106000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 3107000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3108965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 3109c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 3110965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3111965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3112965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3113a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]", 3114c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 3115965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3116965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 3117000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCttsTableEntries->get(duration, 1)); 3120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back host byte order 3121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1); 3122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 3123965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 3124965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 3125965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 3127b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 3128b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 3130b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 3131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 313225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 3133b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 3134b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 3135b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 3137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 3138b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 3139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 314020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 3142b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 3143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 3145b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 3146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 314720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 3149b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 3150b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 3152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 3153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 3154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 3155b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 315720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 315820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 315907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 316007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 316107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 316207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 316307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 316407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 3165e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() { 3166e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("hdlr"); 3167e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3168e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Predefined 3169e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3170e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[0] 3171e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[1] 3172e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[2] 3173e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt8(0); // Name (empty) 3174e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3175e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3176e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3177e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() { 3178e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3179e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3180e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("keys"); 3181e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3182e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(count); // Entry_count 3183e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3184e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3185e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3186e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t n = strlen(key); 3187e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(n + 8); 3188e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3189e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang write(key, n); // write without the \0 3190e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3191e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3192e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3193e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3194e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() { 3195e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3196e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3197e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("ilst"); 3198e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3199e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox(i + 1); // key id (1-based) 3200e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("data"); 3201e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3202e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3203e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang switch (type) { 32047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang case AMessage::kTypeString: 32057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang { 32067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang AString val; 32077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang CHECK(mMetaKeys->findString(key, &val)); 32087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(1); // type = UTF8 32097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 32107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang write(val.c_str(), strlen(val.c_str())); // write without \0 32117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang break; 32127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 32137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 3214e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeFloat: 3215e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3216e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang float val; 3217e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findFloat(key, &val)); 32187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(23); // type = float32 32197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3220e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(*reinterpret_cast<int32_t *>(&val)); 3221e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3222e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3223e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3224e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeInt32: 3225e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3226e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang int32_t val; 3227e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findInt32(key, &val)); 32287c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(67); // type = signed int32 32297c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3230e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(val); 3231e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3232e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3233e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3234e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang default: 3235e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3236e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang ALOGW("Unsupported key type, writing 0 instead"); 32377c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(77); // type = unsigned int32 32387c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3239e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 3240e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3241e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3242e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3243e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // data 3244e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // key id 3245e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3246e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // ilst 3247e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3248e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3249e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() { 3250e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3251e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (count == 0) { 3252e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return; 3253e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3254e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3255e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("meta"); 3256e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeHdlr(); 3257e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeKeys(); 3258e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeIlst(); 3259e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3260e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3261e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 326207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 326307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 326407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 326507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 326607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 326707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 326807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 326907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 327007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 3271432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 3272432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 327307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 327407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 327507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 327607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 327707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 327807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 327907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 328007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 328120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3282