MPEG4Writer.cpp revision 0ca31521644b9396829850f7400d23f9b107cc64
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); 1162177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia // Ensure no integer overflow on allocation in add(). 1172177f21c1ae5bf5cb8c1113a1adbe1fd7db34206Wei Jia CHECK_LT(mEntryCapacity, UINT32_MAX / mElementCapacity); 118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Free the allocated memory. 121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ~ListTableEntries() { 122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (!mTableEntryList.empty()) { 123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete[] (*it); 125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.erase(it); 126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Replace the value at the given position by the given value. 130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // There must be an existing value at the given position. 131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order 132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void set(const TYPE& value, uint32_t pos) { 13425f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity); 135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value; 146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Get the value at the given position by the given value. 149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value the retrieved value at the position in network byte order. 150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @return true if a value is found. 152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool get(TYPE& value, uint32_t pos) const { 15325f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong if (pos >= mTotalNumTableEntries * mEntryCapacity) { 154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return false; 155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong value = (*it)[(pos % (mElementCapacity * mEntryCapacity))]; 167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return true; 168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Store a single value. 171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order. 172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void add(const TYPE& value) { 173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nValues = mNumValuesInCurrEntry % mEntryCapacity; 176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries == 0 && nValues == 0) { 177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity]; 178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCurrTableEntriesElement != NULL); 179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.push_back(mCurrTableEntriesElement); 180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t pos = nEntries * mEntryCapacity + nValues; 183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement[pos] = value; 184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mNumValuesInCurrEntry; 186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) { 187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mTotalNumTableEntries; 188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry = 0; 189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Write out the table entries: 193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 1. the number of entries goes first 194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 2. followed by the values in the table enties in order 195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg writer the writer to actual write to the storage 196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void write(MPEG4Writer *writer) const { 197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0); 198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries; 199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->writeInt32(nEntries); 200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong it != mTableEntryList.end(); ++it) { 202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(nEntries, 0); 203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries >= mElementCapacity) { 204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity); 205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong nEntries -= mElementCapacity; 206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries); 208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong break; 209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Return the number of entries in the table. 214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count() const { return mTotalNumTableEntries; } 215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong private: 217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mElementCapacity; // # entries in an element 218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mEntryCapacity; // # of values in each entry 219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mTotalNumTableEntries; 220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mNumValuesInCurrEntry; // up to mEntryCapacity 221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong TYPE *mCurrTableEntriesElement; 222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mutable List<TYPE *> mTableEntryList; 223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong }; 226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 231693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 233a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 234a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 235eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 2361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 2371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 2381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 239bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 240c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 24143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 242e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 243d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 2441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 2458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 249be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 25013aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 2511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool mSamplesHaveSameSize; 253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStszTableEntries; 254be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStcoTableEntries; 256c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<off64_t> *mCo64TableEntries; 257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStscTableEntries; 258c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStssTableEntries; 259c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mSttsTableEntries; 260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mCttsTableEntries; 261965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 262000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMinCttsOffsetTimeUs; 263000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMaxCttsOffsetTimeUs; 264965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 2663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 2673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 2683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 2693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 2703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 2713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 2723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 2733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 2743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 2753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 2763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 2773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 2783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 281548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 28293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 28425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 2853c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 28670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 28770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 28893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 28993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 29025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 291872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 292872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 293872a481558350634a3fd5cb67939de288af00ecbJames Dong 294000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int32_t getStartTimeOffsetScaledTime() const; 295000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 29737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 3003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 3013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 305215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 306215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 307faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 30893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 30903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 31019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 31119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 312c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 313c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 314c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 315c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 316c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 317c059860c73678a202bfa33062723e8f82fb779d9James Dong 318690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 319690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 32013f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t mRotation; 321690f546b0ee548dbfe997df36418e5302ec2d786James Dong 3221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 3231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 3241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 32579761ab096f57c3027fad9556c2bc436672d614eJames Dong 32679761ab096f57c3027fad9556c2bc436672d614eJames Dong // Duration is time scale based 32779761ab096f57c3027fad9556c2bc436672d614eJames Dong void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 328965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 32945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 33045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong bool isTrackMalFormed() const; 33143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 3321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 339965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void writeCttsBox(); 340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 347efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeMdhdBox(uint32_t now); 348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 351efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeTkhdBox(uint32_t now); 352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36230ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 363674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(dup(fd)), 364674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(mFd < 0? NO_INIT: OK), 365de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording(true), 366b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 3671acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 368a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 369a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 370a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 371411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 37230ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 37313aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 374e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mMoovBoxBuffer(NULL), 375e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mMoovBoxBufferOffset(0), 376e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mWriteMoovBoxToMemory(false), 377e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mFreeBoxOffset(0), 378e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mStreamableFile(false), 3797837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 3807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize(0), 38107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 382e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mTimeScale(-1), 383e502b443ce9d229d1e9108834887c6e520948816Chong Zhang mStartTimestampUs(-1ll), 38407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 38507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 38686b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 387ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar mStartTimeOffsetMs(-1), 388ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar mMetaKeys(new AMessage()) { 3897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang addDeviceMeta(); 3902aa74dc097fe860abc84769abf2b6e0962718471Robert Shih 3912aa74dc097fe860abc84769abf2b6e0962718471Robert Shih // Verify mFd is seekable 3922aa74dc097fe860abc84769abf2b6e0962718471Robert Shih off64_t off = lseek64(mFd, 0, SEEK_SET); 3932aa74dc097fe860abc84769abf2b6e0962718471Robert Shih if (off < 0) { 3942aa74dc097fe860abc84769abf2b6e0962718471Robert Shih ALOGE("cannot seek mFd: %s (%d)", strerror(errno), errno); 3952aa74dc097fe860abc84769abf2b6e0962718471Robert Shih release(); 3962aa74dc097fe860abc84769abf2b6e0962718471Robert Shih } 39730ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 39830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 39920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 4008bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong reset(); 40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 4031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 4051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 4061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 411dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 412dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 413dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 414dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 415dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 416dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 417dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 418dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 419dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 420dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 421dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 422dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 423dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 424dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 425dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 426dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 427dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 428dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 42984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber int fd, const Vector<String16>& /* args */) const { 430dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 431dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 432dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 433dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 434dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 435dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 436dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 437dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 438c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 43913210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 440377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); 44113210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 442dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 443dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 444dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 445dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 4468b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan// static 4478b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavanconst char *MPEG4Writer::Track::getFourCCForMime(const char *mime) { 4488b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (mime == NULL) { 4498b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 4508b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 4518b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strncasecmp(mime, "audio/", 6)) { 4528b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 4538b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "samr"; 4548b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 4558b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "sawb"; 4568b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 4578b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4a"; 4588b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 4598b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strncasecmp(mime, "video/", 6)) { 4608b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 4618b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "mp4v"; 4628b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 4638b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "s263"; 4648b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 4658b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return "avc1"; 4668b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 4678b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } else { 4688b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan ALOGE("Track (%s) other than video or audio is not supported", mime); 4698b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan } 4708b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan return NULL; 4718b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan} 4728b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan 4732dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 474bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 475bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 47629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Attempt to add source AFTER recording is started"); 477bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 478bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 479acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 480acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // At most 2 tracks can be supported. 481acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.size() >= 2) { 482a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGE("Too many tracks (%zu) to add", mTracks.size()); 483acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 484acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 485acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 486acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong CHECK(source.get() != NULL); 487acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 488acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong const char *mime; 489acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong source->getFormat()->findCString(kKeyMIMEType, &mime); 490acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong bool isAudio = !strncasecmp(mime, "audio/", 6); 4918b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (Track::getFourCCForMime(mime) == NULL) { 4928b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan ALOGE("Unsupported mime '%s'", mime); 493acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 494acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 495acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 496acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // At this point, we know the track to be added is either 497acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // video or audio. Thus, we only need to check whether it 498acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // is an audio track or not (if it is not, then it must be 499acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // a video track). 500acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 501acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // No more than one video or one audio track is supported. 502acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong for (List<Track*>::iterator it = mTracks.begin(); 503acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong it != mTracks.end(); ++it) { 504acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if ((*it)->isAudio() == isAudio) { 505acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("%s track already exists", isAudio? "Audio": "Video"); 506acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 507acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 508acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 509acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 510acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // This is the first track of either audio or video. 511acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // Go ahead to add the track. 512219f195159f93d627af2b243732e3f9020511a46James Dong Track *track = new Track(this, source, 1 + mTracks.size()); 51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 5142dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 5152dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 51893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 519acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.empty()) { 520acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("No source added"); 521acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return INVALID_OPERATION; 522acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 523acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 524a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 525a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 52693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 527a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 528a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 529a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 530a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 531a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 532a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 533a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 534a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 535a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 536a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 537a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 538a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 539a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 5407c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() { 5417c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // add device info and estimate space in 'moov' 5427c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang char val[PROPERTY_VALUE_MAX]; 5437c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size_t n; 5447c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // meta size is estimated by adding up the following: 5457c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - meta header structures, which occur only once (total 66 bytes) 5467c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - size for each key, which consists of a fixed header (32 bytes), 5477c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // plus key length and data length. 5487c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 66; 5497c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.version.release", val, NULL) 5507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 5517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Version, val, n + 1); 5527c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32; 5537c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 5547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD 5557c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.product.model", val, NULL) 5567c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 5577c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Model, val, n + 1); 5587c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32; 5597c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 5607c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.display.id", val, NULL) 5617c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 5627c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Build, val, n + 1); 5637c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32; 5647c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 5657c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif 5667c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang} 5677c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 5682dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 5692dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 5702dec2b5be2056c6d9428897dc672185872d30d17James Dong // 5712dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 5722dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 5732dec2b5be2056c6d9428897dc672185872d30d17James Dong 57478a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 5752dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 57678a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 5772dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 5782dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 5792dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 5802dec2b5be2056c6d9428897dc672185872d30d17James Dong 5812dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 5822dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 5832dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 58478a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 5852dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 5862dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 5872dec2b5be2056c6d9428897dc672185872d30d17James Dong 58878a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 589a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 59078a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 59178a1a286f736888ae7af8860b2c424af0d978848James Dong } 59278a1a286f736888ae7af8860b2c424af0d978848James Dong 59378a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 59478a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 59578a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 59678a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 5970ca31521644b9396829850f7400d23f9b107cc64Johan Redestig ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000; 59878a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 59978a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 60078a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 60178a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 60278a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 60378a1a286f736888ae7af8860b2c424af0d978848James Dong } 60478a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 60578a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 60678a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 60778a1a286f736888ae7af8860b2c424af0d978848James Dong } 6082dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6092dec2b5be2056c6d9428897dc672185872d30d17James Dong } 61078a1a286f736888ae7af8860b2c424af0d978848James Dong 6112dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 6122dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 6132dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6142dec2b5be2056c6d9428897dc672185872d30d17James Dong 6152dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 6162dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 6172dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 6182dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 6192dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6202dec2b5be2056c6d9428897dc672185872d30d17James Dong 6217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // Account for the extra stuff (Geo, meta keys, etc.) 6227c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size += mMoovExtraSize; 6237c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 624a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the" 625a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn " estimated moov size %" PRId64 " bytes", 6262dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 6272dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 6282dec2b5be2056c6d9428897dc672185872d30d17James Dong} 6292dec2b5be2056c6d9428897dc672185872d30d17James Dong 6302dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 631674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 63225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 635a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 636a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 637a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 638a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 639a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 640a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 641a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 642a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 643a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 644a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 6452dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 6462dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 6472dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 6482dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 6492dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 6502dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6512dec2b5be2056c6d9428897dc672185872d30d17James Dong 6521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 6531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 6541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 6551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 6561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 6581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 6591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 6601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 661a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. " 662a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn "It is changed to %" PRId64 " bytes", 663d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 664d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 6651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 668b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 669b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 670b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 671b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 672b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 6732dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6742dec2b5be2056c6d9428897dc672185872d30d17James Dong 675de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui int32_t isRealTimeRecording; 676de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) { 677de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording = isRealTimeRecording; 678de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 679de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 680065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 68193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 682a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 683a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 684a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 68593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 686a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 687a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 688a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 689a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 6908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 6918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 6928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 6938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 69443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 6953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("movie time scale: %d", mTimeScale); 6968f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 69777e8ae9967a078770416619e99ddb5b010def312James Dong /* 69877e8ae9967a078770416619e99ddb5b010def312James Dong * When the requested file size limit is small, the priority 69977e8ae9967a078770416619e99ddb5b010def312James Dong * is to meet the file size limit requirement, rather than 7007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to make the file streamable. mStreamableFile does not tell 7017b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * whether the actual recorded file is streamable or not. 70277e8ae9967a078770416619e99ddb5b010def312James Dong */ 70377e8ae9967a078770416619e99ddb5b010def312James Dong mStreamableFile = 70477e8ae9967a078770416619e99ddb5b010def312James Dong (mMaxFileSizeLimitBytes != 0 && 70577e8ae9967a078770416619e99ddb5b010def312James Dong mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 70677e8ae9967a078770416619e99ddb5b010def312James Dong 7077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong /* 7087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory is true if the amount of data in moov box is 7097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * smaller than the reserved free space at the beginning of a file, AND 7107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * when the content of moov box is constructed. Note that video/audio 7117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * frame data is always written to the file but not in the memory. 7127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Before stop()/reset() is called, mWriteMoovBoxToMemory is always 7147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * false. When reset() is called at the end of a recording session, 7157b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Moov box needs to be constructed. 7167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory 7187b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to set to mStreamableFile so that if 7197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the file is intended to be streamable, it is set to true; 7207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * otherwise, it is set to false. When the value is set to false, 7217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * all the content of the moov box is written immediately to 7227b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the end of the file. When the value is set to true, all the 7237b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * content of the moov box is written to an in-memory cache, 7247b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mMoovBoxBuffer, util the following condition happens. Note 7257b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * that the size of the in-memory cache is the same as the 7267b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * reserved free space at the beginning of the file. 7277b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 2) While the data of the moov box is written to an in-memory 7297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache, the data size is checked against the reserved space. 7307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * If the data size surpasses the reserved space, subsequent moov 7317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * data could no longer be hold in the in-memory cache. This also 7327b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * indicates that the reserved space was too small. At this point, 7337b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * _all_ moov data must be written to the end of the file. 7347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory must be set to false to direct the write 7357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to the file. 7367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 7377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 3) If the data size in moov box is smaller than the reserved 7387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space after moov box is completely constructed, the in-memory 7397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache copy of the moov box is written to the reserved free 7407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space. Thus, immediately after the moov is completedly 7417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * constructed, mWriteMoovBoxToMemory is always set to false. 7427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong */ 7437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 7447837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 7457837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 7467837c17063a4c50bc856ba59418516fdab731de7James Dong 747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7497837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7517837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 7522dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 7532dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 7542dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 7552dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7562dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 7577837c17063a4c50bc856ba59418516fdab731de7James Dong } 75843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mEstimatedMoovBoxSize, 8); 75977e8ae9967a078770416619e99ddb5b010def312James Dong if (mStreamableFile) { 76077e8ae9967a078770416619e99ddb5b010def312James Dong // Reserve a 'free' box only for streamable file 76177e8ae9967a078770416619e99ddb5b010def312James Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 76277e8ae9967a078770416619e99ddb5b010def312James Dong writeInt32(mEstimatedMoovBoxSize); 76377e8ae9967a078770416619e99ddb5b010def312James Dong write("free", 4); 76477e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 76577e8ae9967a078770416619e99ddb5b010def312James Dong } else { 76677e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mOffset; 76777e8ae9967a078770416619e99ddb5b010def312James Dong } 7687837c17063a4c50bc856ba59418516fdab731de7James Dong 7697837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 770c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 7711acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 7721acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 7731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 7741acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 7751acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 7761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 7781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 7791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 7801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 7811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 783a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 784a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 7861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 787a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 78825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 78920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 7921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 7931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 7941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 79537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 796674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 79737187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 798a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 799a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 80037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 801a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 802a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 80337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 80437187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 80537187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 80637187916a486504acaf83bea30147eb5fbf46ae5James Dong } 807a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 80837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 809a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 810a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 8111c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 812b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping writer thread"); 813411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 814411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 815411ba422e3635d534928ffd81abf54f4f291c739James Dong } 8161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 8181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 8191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 8211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 8221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 8251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 826411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 827b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Writer thread stopped"); 8281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 8291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 83013f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 83113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 83213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 83313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 83413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 83513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 83613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 83713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 83813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 83913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 84013f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 84113f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 8423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeCompositionMatrix"); 84313f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 84413f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 84513f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 84613f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 84713f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 84813f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 84913f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 85013f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 85113f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 85213f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 85313f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 85413f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 85513f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 85613f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 85713f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 85813f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 85913f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 86013f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 86113f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 86213f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 86313f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 86413f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 86513f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 86613f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 86713f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 86813f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 86913f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 87013f6284305e4b27395a23db7882d670bdb1bcae1James Dong 87113f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 87213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 87313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 87413f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 87513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 87613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 87713f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 87813f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 87913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 88013f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 88113f6284305e4b27395a23db7882d670bdb1bcae1James Dong 882411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 883411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 884411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 885411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 886411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 8874c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary free(mMoovBoxBuffer); 8884c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary mMoovBoxBuffer = NULL; 889411ba422e3635d534928ffd81abf54f4f291c739James Dong} 89013f6284305e4b27395a23db7882d670bdb1bcae1James Dong 8918bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() { 892674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 89337187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 894411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 895411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 896411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 897411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 898411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 899411ba422e3635d534928ffd81abf54f4f291c739James Dong } 900411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 901411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 902411ba422e3635d534928ffd81abf54f4f291c739James Dong } 90320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 90537187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 9068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 90765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 91037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 91137187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 91237187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 91337187916a486504acaf83bea30147eb5fbf46ae5James Dong } 91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 9168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 9178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 91965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 92065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 92165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 92265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 92365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 92465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 925a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us", 92665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 92820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 9307837c17063a4c50bc856ba59418516fdab731de7James Dong 93137187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 93237187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 933411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 93437187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 93537187916a486504acaf83bea30147eb5fbf46ae5James Dong } 93637187916a486504acaf83bea30147eb5fbf46ae5James Dong 93720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 9381acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 939c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 9401f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); 941c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 9421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 943c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 9441f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint64_t size = mOffset - mMdatOffset; 9451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 946c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 9471acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 948c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Construct moov box now 9517837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 9527b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = mStreamableFile; 9537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 9547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // There is no need to allocate in-memory cache 9557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // for moov box if the file is not streamable. 9567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 9577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 9587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong CHECK(mMoovBoxBuffer != NULL); 9597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 96120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // mWriteMoovBoxToMemory could be set to false in 9637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // MPEG4Writer::write() method 9647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 9657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 9667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Content of the moov box is saved in the cache, and the in-memory 9677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // moov box needs to be written to the file in a single shot. 9687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 96943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 9707837c17063a4c50bc856ba59418516fdab731de7James Dong 9717837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 972c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 9737837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 974674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 9757837c17063a4c50bc856ba59418516fdab731de7James Dong 9767837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 977c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 9787837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 9797837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 9807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } else { 9817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ALOGI("The mp4 file will not be streamable."); 9827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 9837837c17063a4c50bc856ba59418516fdab731de7James Dong 9847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Free in-memory cache for moov box 9857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mMoovBoxBuffer != NULL) { 9867837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 9877837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 9887837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 9897837c17063a4c50bc856ba59418516fdab731de7James Dong } 9907837c17063a4c50bc856ba59418516fdab731de7James Dong 9910c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 99220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 993411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 99437187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 99620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 997efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() { 998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 999efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 1000efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // while time function returns Unix epoch values which starts 1001efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // at 1970-01-01. Lets add the number of seconds between them 1002ecf509a9211ca168ffa98c5992f3a4f5f32106cfMarco Nelissen static const uint32_t delta = (66 * 365 + 17) * (24 * 60 * 60); 1003ecf509a9211ca168ffa98c5992f3a4f5f32106cfMarco Nelissen if (now < 0 || uint32_t(now) > UINT32_MAX - delta) { 1004ecf509a9211ca168ffa98c5992f3a4f5f32106cfMarco Nelissen return 0; 1005ecf509a9211ca168ffa98c5992f3a4f5f32106cfMarco Nelissen } 1006ecf509a9211ca168ffa98c5992f3a4f5f32106cfMarco Nelissen uint32_t mpeg4Time = uint32_t(now) + delta; 1007efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson return mpeg4Time; 1008efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson} 1009efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson 1010efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 1011efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 1012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 1013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 1014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 1015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 1016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 1017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 1018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 1019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 1020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 1021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 1022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 1024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 1025b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1030b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 1031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 1032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 1033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 1036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 1037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 103807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 103907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 104007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 1041e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeMetaBox(); 1042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 1043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 1044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 1045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 1046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 1048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 10502cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 1051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 1052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 1054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 1055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 1056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 10578284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 10588284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("isom"); 10598284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("3gp4"); 1060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 10618284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 10628284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 1063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 10648284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 1065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 1068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 107007ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 107107ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 107207ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 107307ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 107407ec01904613a0bac32caaa8444b4690998faed7James Dong 107507ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 107607ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 107707ec01904613a0bac32caaa8444b4690998faed7James Dong char value[PROPERTY_VALUE_MAX]; 107807ec01904613a0bac32caaa8444b4690998faed7James Dong if (property_get("rw.media.record.test", value, NULL) && 107907ec01904613a0bac32caaa8444b4690998faed7James Dong (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 108007ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 108107ec01904613a0bac32caaa8444b4690998faed7James Dong } 108207ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 108307ec01904613a0bac32caaa8444b4690998faed7James Dong} 108407ec01904613a0bac32caaa8444b4690998faed7James Dong 108570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 108607ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 108707ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 108807ec01904613a0bac32caaa8444b4690998faed7James Dong return; 108907ec01904613a0bac32caaa8444b4690998faed7James Dong } 109007ec01904613a0bac32caaa8444b4690998faed7James Dong 109170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 109270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 109370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 109470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 109570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 109670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 109770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 109870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 109970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 110013aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 110113aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 110213aec890216948b0c364f8f92792129d0335f506James Dong return OK; 110313aec890216948b0c364f8f92792129d0335f506James Dong} 110413aec890216948b0c364f8f92792129d0335f506James Dong 110513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 110613aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 110713aec890216948b0c364f8f92792129d0335f506James Dong} 110813aec890216948b0c364f8f92792129d0335f506James Dong 110913aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 111013aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 111113aec890216948b0c364f8f92792129d0335f506James Dong} 111220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1113c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 1114c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1116c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1117c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1118c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 112020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 112220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 112320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 112420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 112503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 112603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 112703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 112803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 112903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 113003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 113103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 113203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 113303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 113403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 113503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 113603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 113703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 113803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1139c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 1140c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 114130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 114230ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 114303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1144b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 1145b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 1146c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1147b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 1148c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1149b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 1150c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1151b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1152c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1153c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 1154c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1155c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1156c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 1157b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1158b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 1159b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 116043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(length, 65536); 116130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1162b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 1163c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1164b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1165c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1166c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1167b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 1168b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 116930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 117030ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 117130ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 117230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 11737837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 1174674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 11757837c17063a4c50bc856ba59418516fdab731de7James Dong 11767837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 11777837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 11787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 1179c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 11801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 11817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // The reserved moov box at the beginning of the file 11827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // is not big enough. Moov box should be written to 11837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the end of the file from now on, but not to the 11847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // in-memory cache. 11857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 11867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // We write partial moov box that is in the memory to 11877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the file first. 1188c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 11897837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 11907837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 11917837c17063a4c50bc856ba59418516fdab731de7James Dong } 1192674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 1193674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 11947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ::write(mFd, ptr, bytes); 11957837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 11967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 11977b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // All subsequent moov box content will be written 11987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // to the end of the file. 11997837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 12007837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 12017837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 12027837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 12037837c17063a4c50bc856ba59418516fdab731de7James Dong } 12047837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1205674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 12067837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 12077837c17063a4c50bc856ba59418516fdab731de7James Dong } 12087837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 12097837c17063a4c50bc856ba59418516fdab731de7James Dong} 12107837c17063a4c50bc856ba59418516fdab731de7James Dong 1211e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) { 1212e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mBoxes.push_back(mWriteMoovBoxToMemory? 1213e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mMoovBoxBufferOffset: mOffset); 1214e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 1215e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 1216e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(id); 1217e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1218e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 12200c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12227837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 12237837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 122420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 12300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1232c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12357837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 12367837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 12377837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 12387837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1239c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 12407837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 12417837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1242c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 12437837c17063a4c50bc856ba59418516fdab731de7James Dong } 124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1247674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 124920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1252674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1257674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 125920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1262674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 126320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 126420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1267674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 126820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 126920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 12710c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 1272674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 127320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 127507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 127607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 127707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 127807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 127907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 128007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 128107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 128207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 128307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 128407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 128507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 128607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 128707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 128807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 128907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 129007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 129107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 129207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 129307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 129407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 129507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 129607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 129707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 129807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 129907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 130007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 130107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 130207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 130307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 130407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 130507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 130607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 130707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 130807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 130907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 131007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 131107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 131207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 131307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 131407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 131507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 131607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 131707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 131807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 131907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 132007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 132107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 132207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 132307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 132407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 132507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 132607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 132707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 132807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 132907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 133007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 133107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 133207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 133307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 133407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 133507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 133607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 133707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 133807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 133907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 134007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 134107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 134207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 13437c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 30; 134407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 134507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 134607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 1347e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) { 1348e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (captureFps <= 0.0f) { 1349e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return BAD_VALUE; 1350e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 1351e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 13527c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps); 13537c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32; 13547c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 1355e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return OK; 1356e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1357e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1359674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136278a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 136378a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 136478a1a286f736888ae7af8860b2c424af0d978848James Dong} 136578a1a286f736888ae7af8860b2c424af0d978848James Dong 1366d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1367d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1368d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1369d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1370d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1371d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1372956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1373d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1374d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1375d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1376d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 13771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 137877e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 137977e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 138077e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 138177e8ae9967a078770416619e99ddb5b010def312James Dong } 1382acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1383acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1384acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1385acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1386d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1387d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1388d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1389d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1390d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1391d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1392d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1393d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1394d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1395d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1396d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1397d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1398d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1399d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1400d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1401d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1402d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 140325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 140425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 140525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 140625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 140725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 140825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 140925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 141025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 141125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 141225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 141325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 141425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 141525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1416f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1417a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("setStartTimestampUs: %" PRId64, timeUs); 141843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 14193c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1420065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1421f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1422a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs); 14233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 14243c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 14253c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1426f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 14273c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 14283c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 14293c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 14303c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 143158ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 143258ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 143358ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 143458ae9c530247668f8af36e30d228c716c226b3d4James Dong} 143558ae9c530247668f8af36e30d228c716c226b3d4James Dong 143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 143820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1439bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 144125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1444a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1445a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1446eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1447bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1448c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1449956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1450be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1451c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1452c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1453c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)), 1454c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)), 1455c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1456c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 1457c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 145820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 145925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1460548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 146113f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 146213f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 146319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 14648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 14651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 14661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 14671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 14681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 14691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 14701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 14711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1472c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1473c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1474c059860c73678a202bfa33062723e8f82fb779d9James Dong 14751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 14761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1477c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1478c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 1479c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 1480c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1481c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 14821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 148378a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 148478a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 148578a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 148678a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1487c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1488c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1489c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1490c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 149178a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 149278a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 149378a1a286f736888ae7af8860b2c424af0d978848James Dong } 14941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 14971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 14981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1499c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(chunkId)); 1500c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(sampleId)); 1501c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(1)); 15021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 15031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 15041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1505c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 15061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 15071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 15081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 150979761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 15101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 15115a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 1512377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGW("0-duration samples found: %zu", sampleCount); 15135a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1514c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1515c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 15161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 15171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1518965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1519965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1520965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1521965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { 1522965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1523965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1524c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1525c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1526965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1527965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1528c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1529c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1530c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1531c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1532c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1533c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1534c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 15351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 15361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1537c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 15383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 1539c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1540c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1541c059860c73678a202bfa33062723e8f82fb779d9James Dong 1542c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1543c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1544c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1545c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1546c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1547c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1548c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1549c059860c73678a202bfa33062723e8f82fb779d9James Dong 1550c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1551c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1552c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1553c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1554c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1555c059860c73678a202bfa33062723e8f82fb779d9James Dong 155643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 155719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 155819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 155919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 156019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 156119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 156219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 156319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 156419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 156519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 156619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 156719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 156819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 156919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 157019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 157119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 157219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 157319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 157419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 157519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 157619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 157719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 157819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 157919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 158019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 158119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 158219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 158319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 158419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 158519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 158619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 158719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 158920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 159020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 159120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 159220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1593c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 1594c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 1595c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 1596c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 1597c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 1598c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 1599c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 1600c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 1601c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 1602c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 1603c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 1604c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 1605c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 1606c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 1607c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 1608c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 160920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 161020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 161120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 161220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 161320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 161420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 161593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 16163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 161793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 161893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 161993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 162093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 162193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 162293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 1623a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs); 162493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 162593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 162693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 162793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 162893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 162993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 16301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 16311c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 16323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 16331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 16341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 16351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 16361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16381c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 16393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 16401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 16411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 16421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 16441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 16451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 16471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 16481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 16491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 16501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 165343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 16541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1656fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1657a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("writeChunkToFile: %" PRId64 " from %s track", 16585410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video"); 1659fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1660fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1661fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1662fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1663fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1664fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong off64_t offset = chunk->mTrack->isAvc() 1665fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong ? addLengthPrefixedSample_l(*it) 1666fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1667fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1668fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1669fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1670fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 16711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 16741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1675fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 16761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1677fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 16781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1680fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 16813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 16821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 168370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 168470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1685e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 168670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 16871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 168870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 168970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 169070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 16911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 1692377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGD("%zu chunks are written in the last batch", outstandingChunks); 16931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1695fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 16963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 16971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 16991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 17001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 17011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 17021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 17031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 17041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 17051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 17061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 17071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 17123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 1713fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 17141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 17171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 17181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1719fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 17201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 17211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 17221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1723fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1724fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1725fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 172670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 172770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 172870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 172970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 173070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 173170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 173270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1733fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 17341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1736fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1737fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 17381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17401c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 17413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 17421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1743a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1744fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1745fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 17461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1747fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1748fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1749fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1750fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 17511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 17521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1754de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // In real time recording mode, write without holding the lock in order 1755de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // to reduce the blocking time for media track threads. 1756de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // Otherwise, hold the lock until the existing chunks get written to the 1757de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // file. 1758fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 1759de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1760de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.unlock(); 1761de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1762fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 1763de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1764de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.lock(); 1765de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1766fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 17671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1768fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1769fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 17701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17721c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 17733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 17761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1777e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 17781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 17791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 17801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 17811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 178270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 178370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 17841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 17851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 17881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 17891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 17901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 17911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 1792411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 17931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 17941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 179793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1798a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1799a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1800a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1801a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1802a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 180325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 180493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 180519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 180619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 180719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 180870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 180919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 181013f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 181113f6284305e4b27395a23db7882d670bdb1bcae1James Dong if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 181213f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 181313f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 181413f6284305e4b27395a23db7882d670bdb1bcae1James Dong 181593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 181693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1817f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1818de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 1819a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 1820a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 1821a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 1822a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 1823a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 1824a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 182586b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 182686b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 1827a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 182886b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 182986b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 183086b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 183186b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 183286b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 1833a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs); 1834a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 1835a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1836f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1837a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1838f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 183925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 184025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 184125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 184225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 184320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 184420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 184520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 184620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 184720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1849eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 1850c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 185125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1852956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 18531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 185443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 185520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 185625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 185720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 185825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 185925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 186020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 186120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 186237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1863a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 186437187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1865a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1866a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 186737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 186872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track stopping", mIsAudio? "Audio": "Video"); 1869eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 187029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 1871eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 1872eaae38445a340c4857c1c5569475879a728e63b7James Dong } 1873eaae38445a340c4857c1c5569475879a728e63b7James Dong 187420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 187537187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 187620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 187720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 187820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 187972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track source stopping", mIsAudio? "Audio": "Video"); 188072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mSource->stop(); 188172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track source stopped", mIsAudio? "Audio": "Video"); 188272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 188320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 188420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 1885377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 188637187916a486504acaf83bea30147eb5fbf46ae5James Dong 1887b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%s track stopped", mIsAudio? "Audio": "Video"); 188837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 188920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 189020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 189125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 189225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 189325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 189425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 189520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 189620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 189720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 189820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 189937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 1900377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT return (void *)(uintptr_t)err; 190120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 190220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 19043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 19073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 19083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 19093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 19113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 19123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 1913a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("findNextStartCode: %p %zu", data, length); 19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 19163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 19223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 19253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 19303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 193629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 19373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 19383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 19413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 19423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 194329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 19453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 19473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 19483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 19493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 19503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 19513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 19523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 19533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 195429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 19553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 19563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 19593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 19603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 19613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 19633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 19643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 19663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 19673856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 19683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 19703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 19713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 1972377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 19733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 19773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 19783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 19793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 19803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 19813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 19833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 19843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 19863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 19873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 19883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 19893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 19903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 19913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 19923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 19933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 19943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 19953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 19963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 19973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 19983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 19993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 20003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 200129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 20053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 20063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 201029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 20113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 201829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 20193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 20233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 20273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 20283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 20293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 20303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 20333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 20343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 20353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 203629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 20373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 2041377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 20423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 20473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 20483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 20493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 205029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 20513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 2054377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 20553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20581374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 20591374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 20601374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 20611374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 20623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 20633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 20643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 20653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 20663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 206729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 20683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 20693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20711374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 20723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 20733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 2074548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 207503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 207603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 2077548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 207803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 207929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 208003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 208103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 208203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 2084377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 208503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 208603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 208703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 20903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 209103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 209203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 209403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 209503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 209603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 20983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 209903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 210003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 21013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 21023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 21033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 21043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 210503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 21063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2107b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2108b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 2109b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2110b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 2111b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 211203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 21133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 21143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 21153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 21163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 21173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 21183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 21193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 21203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 21213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 21223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 21233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 21253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 21263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 21273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 21283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 21303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 21313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 21323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 21333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 21343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 21353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 21363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 21373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 21383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 21393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 21403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 21413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 21423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 21433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 214403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 214503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 214603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 214703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 2148872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 2149872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 2150872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 2151872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 2152872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 2153872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2154872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 2155872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 2156872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2157872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 2158872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2159872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2160872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2161872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 2162872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2163872a481558350634a3fd5cb67939de288af00ecbJames Dong} 2164872a481558350634a3fd5cb67939de288af00ecbJames Dong 216537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 216630ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 216713aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 216843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 216913aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 217013aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 217113aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 2172965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 2173965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 2174965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 2175965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 2176965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 2177000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 2178a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 2179965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 2180000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 2181000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2182000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 218343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 2185e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2186a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 2187a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 2188a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } else { 2189a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 2190a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 2191de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2192de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2193de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2194de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2195985f838934510983d8a887461e98dca60a6e858fJames Dong 2196d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 219720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 219893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 219920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 220011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih const char *trackName = mIsAudio ? "Audio" : "Video"; 220193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 220220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 220320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 220420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 220513aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 220620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 220720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 220820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2209a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 2210a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 2211a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2212a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2213a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2214a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2215a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2216a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2217a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 221830ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 221930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 222003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 222103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 222203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 2223548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 2224548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 22251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 222603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 222703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 222803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 222903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 223043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_EQ((status_t)OK, err); 22311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 223203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 223303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 223403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 223503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 223603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 223703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 223830ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 223930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 224030ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 224130ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 224230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2243548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 224430ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2245a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2246a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2247d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2248d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2249d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2250d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2251d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2252d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2253d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2254d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2255d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2256d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 22571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 2258e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2259b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 2260b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mIsAvc) { 2261b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2262b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2263b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2264b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2265b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2266b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2267050b28a593350047845a45a14cc5026221ac1620James Dong 2268d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 22691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 22701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 22711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2272d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2273d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2274d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2275d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2276d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2277d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2278d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2279d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2280d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2281050b28a593350047845a45a14cc5026221ac1620James Dong 2282d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2283d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2284d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2285d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2286d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2287c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 228870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2289f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2290f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 22918428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 22923c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 229348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2294a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 22958428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 229611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) { 229711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 229811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 229911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 230011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 23018428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 230211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) { 230311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 230411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 230511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 230611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 23078428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2308a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2309a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2310a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2311a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 231211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 231311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 231411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 231511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 231611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2317000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (!mIsAudio) { 2318965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2319965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2320965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2321000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 2322965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 2323965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 2324965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2325965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 2326000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 2327000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 232811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) { 232911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 233011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 233111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 233211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2333965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 2334a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64, 2335000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 2336000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2337000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 2338000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 2339000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 234011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) { 234111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 234211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 234311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 234411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2345c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 234643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 234743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 234843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 234943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 235043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 235143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 235243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 235343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 235443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 235543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 235643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 235743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 235843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 235943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 236043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 2361000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2362000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 2363c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 2364000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2365000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2366000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 2367000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2368000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2369000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2370000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2371000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2372000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2373000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2374965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2375872a481558350634a3fd5cb67939de288af00ecbJames Dong 2376de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2377872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2378872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 2379e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2380e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2381872a481558350634a3fd5cb67939de288af00ecbJames Dong 238211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 238311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 238411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 238511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 238611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2387a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64, 238811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, previousPausedDurationUs); 2389c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2390c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 23913b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 23923b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 23935a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 23945a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 23955a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 23965a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 23975a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 23985a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 23995a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 24005a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2401c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 2402a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGE("timestampUs %" PRId64 " < lastTimestampUs %" PRId64 " for %s track", 240311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih timestampUs, lastTimestampUs, trackName); 240411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2405c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return UNKNOWN_ERROR; 24068c460498c028888c533ab442be12b6d4b669b965James Dong } 24078c460498c028888c533ab442be12b6d4b669b965James Dong 240885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // if the duration is different for this sample, see if it is close enough to the previous 240985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // duration that we can fudge it and use the same value, to avoid filling the stts table 241085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // with lots of near-identical entries. 241185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // "close enough" here means that the current duration needs to be adjusted by less 241285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // than 0.1 milliseconds 241385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { 241485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL 241585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen + (mTimeScale / 2)) / mTimeScale; 241685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (deltaUs > -100 && deltaUs < 100) { 241785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // use previous ticks, and adjust timestamp as if it was actually that number 241885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // of ticks 241985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen currDurationTicks = lastDurationTicks; 242085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen timestampUs += deltaUs; 242185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 242285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 242385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen 2424c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 2425c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 2426c059860c73678a202bfa33062723e8f82fb779d9James Dong 2427a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2428a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2429c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 243079761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2431be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2432be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2433be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2434be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2435965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2436be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2437be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2438c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2439be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2440be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 24418644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2442be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2443a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64, 244411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, lastTimestampUs); 24458644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2446c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 24478644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 244820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2449d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 2450c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 2451d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2452d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 245393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 245493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 245593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 245693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2457faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 245893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 245943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2460c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 246158ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 2462c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2463c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count = (mOwner->use32BitFileOffset() 2464c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 2465c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 2466c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2467c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (count == 0) { 24681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 246958ae9c530247668f8af36e30d228c716c226b3d4James Dong } 247058ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 247158ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 247258ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 247358ae9c530247668f8af36e30d228c716c226b3d4James Dong } 247413aec890216948b0c364f8f92792129d0335f506James Dong 247513aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 247613aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 24771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 24781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 247913aec890216948b0c364f8f92792129d0335f506James Dong } else { 248013aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 248113aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 248213aec890216948b0c364f8f92792129d0335f506James Dong } else { 248343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 248443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 248543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 248643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 248743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 248813aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 248913aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 2490c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 2491c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 2492c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 249313aec890216948b0c364f8f92792129d0335f506James Dong } 24941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 249513aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 249613aec890216948b0c364f8f92792129d0335f506James Dong } 249713aec890216948b0c364f8f92792129d0335f506James Dong } 249813aec890216948b0c364f8f92792129d0335f506James Dong } 249913aec890216948b0c364f8f92792129d0335f506James Dong 250020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 250125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 250245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 2503690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2504f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 250545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2506bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2507be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 250813aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 250943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2510c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(1, mStszTableEntries->count()); 251158ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 25121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 25131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 251413aec890216948b0c364f8f92792129d0335f506James Dong } 251513aec890216948b0c364f8f92792129d0335f506James Dong 2516be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2517be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2518be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2519c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 1) { 25208f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 252179761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2522be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2523be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2524be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2525a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2526c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() <= 2) { 252779761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2528a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 252979761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2530a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2531a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 253279761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2533a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2534a472613aec322e25891abf5c77bf3f7e3c244920James Dong 253543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // The last ctts box may not have been written yet, and this 253643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // is to make sure that we write out the last ctts box. 253743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 253843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (cttsSampleCount > 0) { 253943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 254043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 254143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 254243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 2543c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 254425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 254543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 254643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 254743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2548df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 254911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih count, nZeroLengthFrames, mStszTableEntries->count(), trackName); 2550872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2551a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs()); 2552872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2553365a963142093a1cd8efdcea76b5f65096a5b115James Dong 255437187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 255537187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 255637187916a486504acaf83bea30147eb5fbf46ae5James Dong } 255737187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2558365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2559365a963142093a1cd8efdcea76b5f65096a5b115James Dong 256045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 2561c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { // no samples written 256229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 256345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 256445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 256545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2566c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (!mIsAudio && mStssTableEntries->count() == 0) { // no sync frames for video 256729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 256845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 256945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 257045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 257145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 257245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 257345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 257445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 257545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 257645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 257745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 257843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 257907ec01904613a0bac32caaa8444b4690998faed7James Dong 258007ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 258107ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 258207ec01904613a0bac32caaa8444b4690998faed7James Dong return; 258307ec01904613a0bac32caaa8444b4690998faed7James Dong } 258407ec01904613a0bac32caaa8444b4690998faed7James Dong 258543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 258643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 258743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 258843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 258943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mIsAudio? 0: 1); 259043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 259143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 259243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 259343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 259443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 259543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 259643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2597c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 259843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 259986b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 260086b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 260186b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 260286b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 260386b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 260486b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 260586b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 260686b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 260786b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 260886b7f47aa7482424cf8fd248f1315311919be3b0James Dong 260986b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 261070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 261170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 261286b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 261370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 261407ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 261507ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 261607ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 261707ec01904613a0bac32caaa8444b4690998faed7James Dong 261843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 261943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 262043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 262143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 262270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 262370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 262470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 262570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 262670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 262770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 262870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 262970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 263043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 263143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 263243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2633faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 2634a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("trackProgressStatus: %" PRId64 " us", timeUs); 2635c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2636215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 2637215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 2638a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs); 2639bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 264093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 264193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 264293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 264393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2644faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 2645bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 2646faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 2647bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 2648faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2649faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 2650faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 2651faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 2652bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2653bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2654faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2655faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 2656faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2657faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2658faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 2659faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 2660bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2661bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2662faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2663faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 2664faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 2665bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2666bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2667faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 2668faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2669faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 2670faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2671d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 2672a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs); 2673e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2674d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 2675e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2676e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2677e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 2678a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs); 2679e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2680e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 2681e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2682e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2683de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const { 2684de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui return mIsRealTimeRecording; 2685de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui} 2686de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2687b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 2688b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 2689b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 2690b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 26911c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 26923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 26931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 26941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 26951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 269613aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 269720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 269820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26993b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 2700c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 270120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 270220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2703d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2704d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 2705d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 2706d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2707690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 2708690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 2709690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2710690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2711690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2712690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2713690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2714690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 271529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 2716690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2717690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2718690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2719690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2720690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 272129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 2722690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2723690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2724690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2725690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2726690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2727690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 272920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s track time scale: %d", 27311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 27328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 2733efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 2764965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong writeCttsBox(); 2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mIsAudio) { 2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 2767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 27788b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 27798b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 278029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 27848b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan mOwner->beginBox(fourcc); // video format 2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 2805c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->writeInt8(0); // compressor string length 2806c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->write(" ", 31); 2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 281043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(23 + mCodecSpecificDataSize, 128); 2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 2821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 28288b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan const char *fourcc = getFourCCForMime(mime); 28298b07404cfe564885045a63bb592d6b6dc838b408Praveen Chavan if (fourcc == NULL) { 283029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 2844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 2848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 2849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 2851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 2853b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 2856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 2861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 286343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 286643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(mCodecSpecificDataSize + 23, 128); 2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 2872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 2873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 2878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 2880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2881ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier int32_t bitRate; 2882ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier bool success = mMeta->findInt32(kKeyBitRate, &bitRate); 2883ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier mOwner->writeInt32(success ? bitRate : 96000); // max bit rate 2884ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier mOwner->writeInt32(success ? bitRate : 96000); // avg bit rate 2885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 2901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 290243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 2910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 2916b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 0x77, 0x00, 2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00, 2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00 2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 2923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2939efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 2940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 2942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 2943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2946219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 2947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 29488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 2956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 296120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 2968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 2978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 2979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 2980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 2982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 2988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 2989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 2991b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2993b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3008efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 3010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 3011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 3013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 3014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 3015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 3016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 3017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 3018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 3019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 3020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 3021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 3022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // language code 3023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 3024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3025b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 3028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 3029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 3030b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 3031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 3036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 3039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 3040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 3041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 3042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 3043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 3044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 3047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 3048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 3050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 3051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 3052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3053b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3054b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 3057b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 3058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 3061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 306243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mCodecSpecificDataSize, 5); 3063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 3065b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 3067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 3068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 3069b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3070b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 3071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3073b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 3074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 3075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 3076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3077b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 3078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 3079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 3080b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 3083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 3084b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 3085b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 3086b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 3087b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 3088b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3089b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3090000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 3091a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 3092b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3093b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 309443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 3095b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3096b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3097000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 3098000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 3099000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3100000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 3101000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 3102000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3103c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3104c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mSttsTableEntries->get(duration, 1)); 3105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back to host byte order 3106c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 3107c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 3108b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 3109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 311020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3111965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 3112965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { // ctts is not for audio 3113965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3114965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3115965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3116000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 3117000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 3118000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 3119000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 3120000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3121965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 3122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 3123965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3124965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3125965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3126a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]", 3127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 3128965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3129965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 3130000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCttsTableEntries->get(duration, 1)); 3133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back host byte order 3134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1); 3135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 3136965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 3137965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 3138965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3139b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 3140b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 3141b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 3143b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 3144b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 314525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 3146b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 3147b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 3148b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 3150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 3151b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 3152b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 315320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3154b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 3155b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 3156b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 3158b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 3159b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 316020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3161b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 3162b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 3163b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 3165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 3166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 3167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 3168b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3169b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 317020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 317120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 317207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 317307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 317407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 317507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 317607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 317707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 3178e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() { 3179e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("hdlr"); 3180e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3181e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Predefined 3182e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3183e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[0] 3184e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[1] 3185e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[2] 3186e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt8(0); // Name (empty) 3187e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3188e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3189e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3190e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() { 3191e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3192e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3193e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("keys"); 3194e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3195e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(count); // Entry_count 3196e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3197e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3198e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3199e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t n = strlen(key); 3200e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(n + 8); 3201e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3202e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang write(key, n); // write without the \0 3203e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3204e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3205e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3206e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3207e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() { 3208e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3209e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3210e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("ilst"); 3211e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3212e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox(i + 1); // key id (1-based) 3213e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("data"); 3214e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3215e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3216e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang switch (type) { 32177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang case AMessage::kTypeString: 32187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang { 32197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang AString val; 32207c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang CHECK(mMetaKeys->findString(key, &val)); 32217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(1); // type = UTF8 32227c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 32237c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang write(val.c_str(), strlen(val.c_str())); // write without \0 32247c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang break; 32257c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 32267c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 3227e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeFloat: 3228e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3229e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang float val; 3230e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findFloat(key, &val)); 32317c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(23); // type = float32 32327c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3233e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(*reinterpret_cast<int32_t *>(&val)); 3234e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3235e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3236e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3237e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeInt32: 3238e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3239e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang int32_t val; 3240e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findInt32(key, &val)); 32417c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(67); // type = signed int32 32427c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3243e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(val); 3244e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3245e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3246e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3247e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang default: 3248e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3249e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang ALOGW("Unsupported key type, writing 0 instead"); 32507c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(77); // type = unsigned int32 32517c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3252e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 3253e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3254e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3255e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3256e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // data 3257e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // key id 3258e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3259e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // ilst 3260e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3261e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3262e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() { 3263e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3264e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (count == 0) { 3265e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return; 3266e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3267e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3268e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("meta"); 3269e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeHdlr(); 3270e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeKeys(); 3271e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeIlst(); 3272e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3273e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3274e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 327507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 327607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 327707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 327807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 327907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 328007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 328107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 328207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 328307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 3284432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 3285432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 328607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 328707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 328807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 328907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 329007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 329107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 329207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 329307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 329420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3295