MPEG4Writer.cpp revision ee4e1b1a63758941460ae79a064249d3a5189443
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_Model[] = "com.android.model"; 677c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Version[] = "com.android.version"; 687c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_Build[] = "com.android.build"; 697c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangstatic const char kMetaKey_CaptureFps[] = "com.android.capture.fps"; 707c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 717c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang/* uncomment to include model and build in meta */ 727c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang//#define SHOW_MODEL_BUILD 1 737c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 76bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId); 778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 8137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t stop(); 8237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 8325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 8420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 853b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 86d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 87b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTrackHeader(bool use32BitOffset = true); 881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 92c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong void addChunkOffset(off64_t offset); 9370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int32_t getTrackId() const { return mTrackId; } 94dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 97000e18370baae60ffd9f25b509501dd8c26deabfJames Dong enum { 98000e18370baae60ffd9f25b509501dd8c26deabfJames Dong kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 998c460498c028888c533ab442be12b6d4b669b965James Dong kSampleArraySize = 1000, 100000e18370baae60ffd9f25b509501dd8c26deabfJames Dong }; 101000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 102c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // A helper class to handle faster write box with table entries 103c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong template<class TYPE> 104c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong struct ListTableEntries { 105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity) 106c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mElementCapacity(elementCapacity), 107c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEntryCapacity(entryCapacity), 108c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTotalNumTableEntries(0), 109c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry(0), 110c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement(NULL) { 111c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mElementCapacity, 0); 112c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mEntryCapacity, 0); 113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 114c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 115c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Free the allocated memory. 116c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ~ListTableEntries() { 117c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (!mTableEntryList.empty()) { 118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete[] (*it); 120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.erase(it); 121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Replace the value at the given position by the given value. 125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // There must be an existing value at the given position. 126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order 127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void set(const TYPE& value, uint32_t pos) { 12925f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity); 130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value; 141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Get the value at the given position by the given value. 144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value the retrieved value at the position in network byte order. 145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @return true if a value is found. 147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool get(TYPE& value, uint32_t pos) const { 14825f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong if (pos >= mTotalNumTableEntries * mEntryCapacity) { 149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return false; 150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong value = (*it)[(pos % (mElementCapacity * mEntryCapacity))]; 162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return true; 163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Store a single value. 166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order. 167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void add(const TYPE& value) { 168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nValues = mNumValuesInCurrEntry % mEntryCapacity; 171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries == 0 && nValues == 0) { 172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity]; 173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCurrTableEntriesElement != NULL); 174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.push_back(mCurrTableEntriesElement); 175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t pos = nEntries * mEntryCapacity + nValues; 178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement[pos] = value; 179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mNumValuesInCurrEntry; 181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) { 182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mTotalNumTableEntries; 183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry = 0; 184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Write out the table entries: 188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 1. the number of entries goes first 189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 2. followed by the values in the table enties in order 190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg writer the writer to actual write to the storage 191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void write(MPEG4Writer *writer) const { 192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0); 193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries; 194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->writeInt32(nEntries); 195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong it != mTableEntryList.end(); ++it) { 197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(nEntries, 0); 198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries >= mElementCapacity) { 199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity); 200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong nEntries -= mElementCapacity; 201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries); 203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong break; 204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Return the number of entries in the table. 209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count() const { return mTotalNumTableEntries; } 210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong private: 212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mElementCapacity; // # entries in an element 213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mEntryCapacity; // # of values in each entry 214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mTotalNumTableEntries; 215c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mNumValuesInCurrEntry; // up to mEntryCapacity 216c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong TYPE *mCurrTableEntriesElement; 217c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mutable List<TYPE *> mTableEntryList; 218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong }; 221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 226693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 228a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 229a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 230eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 2311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 2321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 2331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 234bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 235c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 23643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 237e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 238d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 2391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 2408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 244be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 24513aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 2461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool mSamplesHaveSameSize; 248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStszTableEntries; 249be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStcoTableEntries; 251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<off64_t> *mCo64TableEntries; 252c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStscTableEntries; 253c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStssTableEntries; 254c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mSttsTableEntries; 255c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mCttsTableEntries; 256965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 257000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMinCttsOffsetTimeUs; 258000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMaxCttsOffsetTimeUs; 259965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 2613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 2623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 2633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 2643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 2653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 2663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 2673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 2683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 2693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 2703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 2713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 2723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 2733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 276548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 27793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 2803c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 28170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 28270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 28393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 28493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 28525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 286872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 287872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 288872a481558350634a3fd5cb67939de288af00ecbJames Dong 289000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int32_t getStartTimeOffsetScaledTime() const; 290000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 29237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 2953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 2963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 297b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 298b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 299b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 300215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 301215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 302faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 30393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 30403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 30519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 30619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 307c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 308c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 309c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 310c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 311c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 312c059860c73678a202bfa33062723e8f82fb779d9James Dong 313690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 314690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 31513f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t mRotation; 316690f546b0ee548dbfe997df36418e5302ec2d786James Dong 3171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 3181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 3191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 32079761ab096f57c3027fad9556c2bc436672d614eJames Dong 32179761ab096f57c3027fad9556c2bc436672d614eJames Dong // Duration is time scale based 32279761ab096f57c3027fad9556c2bc436672d614eJames Dong void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 323965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 32445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 32545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong bool isTrackMalFormed() const; 32643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 3271f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 334965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void writeCttsBox(); 335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 342efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeMdhdBox(uint32_t now); 343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 346efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeTkhdBox(uint32_t now); 347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35730ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 358674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(dup(fd)), 359674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(mFd < 0? NO_INIT: OK), 360de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording(true), 361b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 3621acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 363a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 364a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 365a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 366411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 36730ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 36813aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 3697837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 3707c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize(0), 37107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 37207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 37307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 37486b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 375ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar mStartTimeOffsetMs(-1), 376ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar mMetaKeys(new AMessage()) { 3777c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang addDeviceMeta(); 37830ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 37930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 38020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 3818bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong reset(); 38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 3841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 3861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 3871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 392dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 393dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 394dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 395dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 396dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 397dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 398dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 399dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 400dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 401dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 402dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 403dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 404dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 405dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 406dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 407dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 408dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 409dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 41084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber int fd, const Vector<String16>& /* args */) const { 411dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 412dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 413dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 414dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 415dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 416dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 417dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 418dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 419c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 42013210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 421377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); 42213210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 423dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 424dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 425dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 426dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 4272dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 428bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 429bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 43029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Attempt to add source AFTER recording is started"); 431bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 432bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 433acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 434acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // At most 2 tracks can be supported. 435acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.size() >= 2) { 436a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGE("Too many tracks (%zu) to add", mTracks.size()); 437acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 438acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 439acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 440acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong CHECK(source.get() != NULL); 441acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 442acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // A track of type other than video or audio is not supported. 443acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong const char *mime; 444acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong source->getFormat()->findCString(kKeyMIMEType, &mime); 445acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong bool isAudio = !strncasecmp(mime, "audio/", 6); 446acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong bool isVideo = !strncasecmp(mime, "video/", 6); 447acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (!isAudio && !isVideo) { 448acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("Track (%s) other than video or audio is not supported", 449acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong mime); 450acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 451acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 452acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 453acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // At this point, we know the track to be added is either 454acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // video or audio. Thus, we only need to check whether it 455acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // is an audio track or not (if it is not, then it must be 456acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // a video track). 457acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 458acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // No more than one video or one audio track is supported. 459acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong for (List<Track*>::iterator it = mTracks.begin(); 460acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong it != mTracks.end(); ++it) { 461acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if ((*it)->isAudio() == isAudio) { 462acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("%s track already exists", isAudio? "Audio": "Video"); 463acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 464acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 465acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 466acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 467acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // This is the first track of either audio or video. 468acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // Go ahead to add the track. 469219f195159f93d627af2b243732e3f9020511a46James Dong Track *track = new Track(this, source, 1 + mTracks.size()); 47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 4712dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 4722dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 47593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 476acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.empty()) { 477acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("No source added"); 478acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return INVALID_OPERATION; 479acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 480acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 481a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 482a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 48393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 484a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 485a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 486a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 487a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 488a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 489a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 490a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 491a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 492a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 493a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 494a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 495a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 496a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 4977c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhangvoid MPEG4Writer::addDeviceMeta() { 4987c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // add device info and estimate space in 'moov' 4997c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang char val[PROPERTY_VALUE_MAX]; 5007c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size_t n; 5017c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // meta size is estimated by adding up the following: 5027c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - meta header structures, which occur only once (total 66 bytes) 5037c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // - size for each key, which consists of a fixed header (32 bytes), 5047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // plus key length and data length. 5057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 66; 5067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.version.release", val, NULL) 5077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 5087c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Version, val, n + 1); 5097c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32; 5107c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 5117c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#ifdef SHOW_MODEL_BUILD 5127c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.product.model", val, NULL) 5137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 5147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Model, val, n + 1); 5157c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32; 5167c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 5177c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang if (property_get("ro.build.display.id", val, NULL) 5187c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang && (n = strlen(val)) > 0) { 5197c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setString(kMetaKey_Build, val, n + 1); 5207c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32; 5217c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 5227c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang#endif 5237c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang} 5247c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 5252dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 5262dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 5272dec2b5be2056c6d9428897dc672185872d30d17James Dong // 5282dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 5292dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 5302dec2b5be2056c6d9428897dc672185872d30d17James Dong 53178a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 5322dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 53378a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 5342dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 5352dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 5362dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 5372dec2b5be2056c6d9428897dc672185872d30d17James Dong 5382dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 5392dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 5402dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 54178a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 5422dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 5432dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 5442dec2b5be2056c6d9428897dc672185872d30d17James Dong 54578a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 546a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 54778a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 54878a1a286f736888ae7af8860b2c424af0d978848James Dong } 54978a1a286f736888ae7af8860b2c424af0d978848James Dong 55078a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 55178a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 55278a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 55378a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 55478a1a286f736888ae7af8860b2c424af0d978848James Dong ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000); 55578a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 55678a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 55778a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 55878a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 55978a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 56078a1a286f736888ae7af8860b2c424af0d978848James Dong } 56178a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 56278a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 56378a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 56478a1a286f736888ae7af8860b2c424af0d978848James Dong } 5652dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5662dec2b5be2056c6d9428897dc672185872d30d17James Dong } 56778a1a286f736888ae7af8860b2c424af0d978848James Dong 5682dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 5692dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 5702dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5712dec2b5be2056c6d9428897dc672185872d30d17James Dong 5722dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 5732dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 5742dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 5752dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 5762dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5772dec2b5be2056c6d9428897dc672185872d30d17James Dong 5787c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang // Account for the extra stuff (Geo, meta keys, etc.) 5797c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang size += mMoovExtraSize; 5807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 581a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the" 582a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn " estimated moov size %" PRId64 " bytes", 5832dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 5842dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 5852dec2b5be2056c6d9428897dc672185872d30d17James Dong} 5862dec2b5be2056c6d9428897dc672185872d30d17James Dong 5872dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 588674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 58925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 592a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 593a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 594a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 595a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 596a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 597a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 598a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 599a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 600a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 601a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 6022dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 6032dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 6042dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 6052dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 6062dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 6072dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6082dec2b5be2056c6d9428897dc672185872d30d17James Dong 6091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 6101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 6111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 6121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 6131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 6151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 6161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 6171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 618a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. " 619a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn "It is changed to %" PRId64 " bytes", 620d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 621d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 6221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 625b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 626b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 627b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 628b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 629b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 6302dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6312dec2b5be2056c6d9428897dc672185872d30d17James Dong 632de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui int32_t isRealTimeRecording; 633de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) { 634de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording = isRealTimeRecording; 635de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 636de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 637065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 63893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 639a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 640a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 641a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 64293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 643a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 644a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 645a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 646a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 6478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 6488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 6498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 6508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 65143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 6523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("movie time scale: %d", mTimeScale); 6538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 65477e8ae9967a078770416619e99ddb5b010def312James Dong /* 65577e8ae9967a078770416619e99ddb5b010def312James Dong * When the requested file size limit is small, the priority 65677e8ae9967a078770416619e99ddb5b010def312James Dong * is to meet the file size limit requirement, rather than 6577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to make the file streamable. mStreamableFile does not tell 6587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * whether the actual recorded file is streamable or not. 65977e8ae9967a078770416619e99ddb5b010def312James Dong */ 66077e8ae9967a078770416619e99ddb5b010def312James Dong mStreamableFile = 66177e8ae9967a078770416619e99ddb5b010def312James Dong (mMaxFileSizeLimitBytes != 0 && 66277e8ae9967a078770416619e99ddb5b010def312James Dong mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 66377e8ae9967a078770416619e99ddb5b010def312James Dong 6647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong /* 6657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory is true if the amount of data in moov box is 6667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * smaller than the reserved free space at the beginning of a file, AND 6677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * when the content of moov box is constructed. Note that video/audio 6687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * frame data is always written to the file but not in the memory. 6697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Before stop()/reset() is called, mWriteMoovBoxToMemory is always 6717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * false. When reset() is called at the end of a recording session, 6727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Moov box needs to be constructed. 6737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory 6757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to set to mStreamableFile so that if 6767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the file is intended to be streamable, it is set to true; 6777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * otherwise, it is set to false. When the value is set to false, 6787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * all the content of the moov box is written immediately to 6797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the end of the file. When the value is set to true, all the 6807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * content of the moov box is written to an in-memory cache, 6817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mMoovBoxBuffer, util the following condition happens. Note 6827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * that the size of the in-memory cache is the same as the 6837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * reserved free space at the beginning of the file. 6847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 2) While the data of the moov box is written to an in-memory 6867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache, the data size is checked against the reserved space. 6877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * If the data size surpasses the reserved space, subsequent moov 6887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * data could no longer be hold in the in-memory cache. This also 6897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * indicates that the reserved space was too small. At this point, 6907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * _all_ moov data must be written to the end of the file. 6917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory must be set to false to direct the write 6927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to the file. 6937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 3) If the data size in moov box is smaller than the reserved 6957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space after moov box is completely constructed, the in-memory 6967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache copy of the moov box is written to the reserved free 6977b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space. Thus, immediately after the moov is completedly 6987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * constructed, mWriteMoovBoxToMemory is always set to false. 6997b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong */ 7007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 7017837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 7027837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 7037837c17063a4c50bc856ba59418516fdab731de7James Dong 704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7067837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7087837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 7092dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 7102dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 7112dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 7122dec2b5be2056c6d9428897dc672185872d30d17James Dong } 7132dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 7147837c17063a4c50bc856ba59418516fdab731de7James Dong } 71543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mEstimatedMoovBoxSize, 8); 71677e8ae9967a078770416619e99ddb5b010def312James Dong if (mStreamableFile) { 71777e8ae9967a078770416619e99ddb5b010def312James Dong // Reserve a 'free' box only for streamable file 71877e8ae9967a078770416619e99ddb5b010def312James Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 71977e8ae9967a078770416619e99ddb5b010def312James Dong writeInt32(mEstimatedMoovBoxSize); 72077e8ae9967a078770416619e99ddb5b010def312James Dong write("free", 4); 72177e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 72277e8ae9967a078770416619e99ddb5b010def312James Dong } else { 72377e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mOffset; 72477e8ae9967a078770416619e99ddb5b010def312James Dong } 7257837c17063a4c50bc856ba59418516fdab731de7James Dong 7267837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 727c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 7281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 7291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 7301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 7311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 7321acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 7331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 7351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 7361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 7371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 7381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 740a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 741a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 7431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 744a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 74525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 7491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 7501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 7511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 75237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 753674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 75437187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 755a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 756a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 75737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 758a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 759a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 76037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 76137187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 76237187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 76337187916a486504acaf83bea30147eb5fbf46ae5James Dong } 764a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 76537187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 766a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 767a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 7681c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 769b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping writer thread"); 770411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 771411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 772411ba422e3635d534928ffd81abf54f4f291c739James Dong } 7731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 7751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 7761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 7781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 7791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 7801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 7821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 783411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 784b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Writer thread stopped"); 7851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 7861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 78713f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 78813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 78913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 79013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 79113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 79213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 79313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 79413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 79513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 79613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 79713f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 79813f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 7993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeCompositionMatrix"); 80013f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 80113f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 80213f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 80313f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 80413f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 80513f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 80613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 80713f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 80813f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 80913f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 81013f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 81113f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 81213f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 81313f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 81413f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 81513f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 81613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 81713f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 81813f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 81913f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 82013f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 82113f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 82213f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 82313f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 82413f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 82513f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 82613f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 82713f6284305e4b27395a23db7882d670bdb1bcae1James Dong 82813f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 82913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 83013f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 83113f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 83213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 83313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 83413f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 83513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 83613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 83713f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 83813f6284305e4b27395a23db7882d670bdb1bcae1James Dong 839411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 840411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 841411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 842411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 843411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 8444c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary free(mMoovBoxBuffer); 8454c845fde3d60ad93984879f69b164e35536e080dSuresh Choudhary mMoovBoxBuffer = NULL; 846411ba422e3635d534928ffd81abf54f4f291c739James Dong} 84713f6284305e4b27395a23db7882d670bdb1bcae1James Dong 8488bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() { 849674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 85037187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 851411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 852411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 853411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 854411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 855411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 856411ba422e3635d534928ffd81abf54f4f291c739James Dong } 857411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 858411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 859411ba422e3635d534928ffd81abf54f4f291c739James Dong } 86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 86237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 8638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 86465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 86520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 86737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 86837187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 86937187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 87037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 87120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 8738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 8748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 87520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 87665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 87765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 87865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 87965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 88065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 88165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 882a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us", 88365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 88420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 88520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 8877837c17063a4c50bc856ba59418516fdab731de7James Dong 88837187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 88937187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 890411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 89137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 89237187916a486504acaf83bea30147eb5fbf46ae5James Dong } 89337187916a486504acaf83bea30147eb5fbf46ae5James Dong 89420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 8951acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 896c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 8971f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); 898c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 8991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 900c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 9011f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint64_t size = mOffset - mMdatOffset; 9021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 903c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 9041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 905c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Construct moov box now 9087837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 9097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = mStreamableFile; 9107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 9117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // There is no need to allocate in-memory cache 9127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // for moov box if the file is not streamable. 9137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 9147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 9157b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong CHECK(mMoovBoxBuffer != NULL); 9167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // mWriteMoovBoxToMemory could be set to false in 9207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // MPEG4Writer::write() method 9217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 9227b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 9237b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Content of the moov box is saved in the cache, and the in-memory 9247b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // moov box needs to be written to the file in a single shot. 9257b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 92643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 9277837c17063a4c50bc856ba59418516fdab731de7James Dong 9287837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 929c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 9307837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 931674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 9327837c17063a4c50bc856ba59418516fdab731de7James Dong 9337837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 934c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 9357837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 9367837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 9377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } else { 9387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ALOGI("The mp4 file will not be streamable."); 9397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 9407837c17063a4c50bc856ba59418516fdab731de7James Dong 9417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Free in-memory cache for moov box 9427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mMoovBoxBuffer != NULL) { 9437837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 9447837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 9457837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 9467837c17063a4c50bc856ba59418516fdab731de7James Dong } 9477837c17063a4c50bc856ba59418516fdab731de7James Dong 9480c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 950411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 95137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 954efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() { 955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 956efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 957efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // while time function returns Unix epoch values which starts 958efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // at 1970-01-01. Lets add the number of seconds between them 959efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60); 960efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson return mpeg4Time; 961efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson} 962efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson 963efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 964efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 99107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 99207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 99307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 994e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeMetaBox(); 995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 1001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 10032cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 1004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 1005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 1007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 1008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 1009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 10108284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 10118284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("isom"); 10128284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("3gp4"); 1013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 10148284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 10158284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 1016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 10178284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 1018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 1019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 1020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 1021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 102307ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 102407ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 102507ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 102607ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 102707ec01904613a0bac32caaa8444b4690998faed7James Dong 102807ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 102907ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 103007ec01904613a0bac32caaa8444b4690998faed7James Dong char value[PROPERTY_VALUE_MAX]; 103107ec01904613a0bac32caaa8444b4690998faed7James Dong if (property_get("rw.media.record.test", value, NULL) && 103207ec01904613a0bac32caaa8444b4690998faed7James Dong (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 103307ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 103407ec01904613a0bac32caaa8444b4690998faed7James Dong } 103507ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 103607ec01904613a0bac32caaa8444b4690998faed7James Dong} 103707ec01904613a0bac32caaa8444b4690998faed7James Dong 103870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 103907ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 104007ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 104107ec01904613a0bac32caaa8444b4690998faed7James Dong return; 104207ec01904613a0bac32caaa8444b4690998faed7James Dong } 104307ec01904613a0bac32caaa8444b4690998faed7James Dong 104470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 104570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 104670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 104770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 104870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 104970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 105070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 105170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 105270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 105313aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 105413aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 105513aec890216948b0c364f8f92792129d0335f506James Dong return OK; 105613aec890216948b0c364f8f92792129d0335f506James Dong} 105713aec890216948b0c364f8f92792129d0335f506James Dong 105813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 105913aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 106013aec890216948b0c364f8f92792129d0335f506James Dong} 106113aec890216948b0c364f8f92792129d0335f506James Dong 106213aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 106313aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 106413aec890216948b0c364f8f92792129d0335f506James Dong} 106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1066c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 1067c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 106820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1069c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1070c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1071c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 107220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 107320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 107420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 107520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 107620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 107720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 107803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 107903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 108003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 108103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 108203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 108303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 108403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 108503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 108603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 108703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 108803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 108903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 109003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 109103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1092c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 1093c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 109430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 109530ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 109603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1097b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 1098b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 1099c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1100b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 1101c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1102b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 1103c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1104b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1105c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1106c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 1107c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1108c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1109c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 1110b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1111b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 1112b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 111343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(length, 65536); 111430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1115b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 1116c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1117b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1118c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1119c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1120b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 1121b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 112230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 112330ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 112430ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 112530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 11267837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 1127674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 11287837c17063a4c50bc856ba59418516fdab731de7James Dong 11297837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 11307837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 11317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 1132c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 11331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 11347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // The reserved moov box at the beginning of the file 11357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // is not big enough. Moov box should be written to 11367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the end of the file from now on, but not to the 11377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // in-memory cache. 11387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 11397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // We write partial moov box that is in the memory to 11407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the file first. 1141c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 11427837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 11437837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 11447837c17063a4c50bc856ba59418516fdab731de7James Dong } 1145674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 1146674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 11477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ::write(mFd, ptr, bytes); 11487837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 11497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 11507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // All subsequent moov box content will be written 11517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // to the end of the file. 11527837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 11537837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 11547837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 11557837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 11567837c17063a4c50bc856ba59418516fdab731de7James Dong } 11577837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1158674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 11597837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 11607837c17063a4c50bc856ba59418516fdab731de7James Dong } 11617837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 11627837c17063a4c50bc856ba59418516fdab731de7James Dong} 11637837c17063a4c50bc856ba59418516fdab731de7James Dong 1164e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::beginBox(uint32_t id) { 1165e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mBoxes.push_back(mWriteMoovBoxToMemory? 1166e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang mMoovBoxBufferOffset: mOffset); 1167e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 1168e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 1169e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(id); 1170e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1171e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 11730c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11757837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 11767837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 11830c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1185c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11887837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 11897837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 11907837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 11917837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1192c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 11937837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 11947837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1195c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 11967837c17063a4c50bc856ba59418516fdab731de7James Dong } 119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1200674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1205674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1210674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1215674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1220674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 122320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 12240c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 1225674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 122807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 122907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 123007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 123107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 123207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 123307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 123407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 123507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 123607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 123707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 123807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 123907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 124007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 124107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 124207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 124307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 124407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 124507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 124607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 124707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 124807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 124907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 125007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 125107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 125207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 125307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 125407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 125507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 125607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 125707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 125807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 125907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 126007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 126107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 126207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 126307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 126407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 126507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 126607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 126707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 126807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 126907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 127007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 127107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 127207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 127307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 127407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 127507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 127607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 127707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 127807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 127907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 128007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 128107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 128207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 128307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 128407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 128507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 128607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 128707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 128807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 128907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 129007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 129107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 129207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 129307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 129407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 129507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 12967c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += 30; 129707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 129807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 129907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 1300e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangstatus_t MPEG4Writer::setCaptureRate(float captureFps) { 1301e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (captureFps <= 0.0f) { 1302e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return BAD_VALUE; 1303e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 1304e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 13057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps); 13067c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32; 13077c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 1308e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return OK; 1309e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 1310e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1312674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 131578a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 131678a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 131778a1a286f736888ae7af8860b2c424af0d978848James Dong} 131878a1a286f736888ae7af8860b2c424af0d978848James Dong 1319d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1320d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1321d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1322d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1323d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1324d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1325956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1326d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1327d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1328d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1329d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 13301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 133177e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 133277e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 133377e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 133477e8ae9967a078770416619e99ddb5b010def312James Dong } 1335acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1336acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1337acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1338acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1339d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1340d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1341d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1342d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1343d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1344d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1345d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1346d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1347d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1348d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1349d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1350d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1351d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1352d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1353d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1354d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1355d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 135625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 135725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 135825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 135925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 136025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 136125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 136225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 136325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 136425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 136525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 136625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 136725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 136825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1369f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1370a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("setStartTimestampUs: %" PRId64, timeUs); 137143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 13723c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1373065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1374f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1375a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs); 13763c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 13773c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 13783c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1379f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 13803c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 13813c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 13823c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 13833c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 138458ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 138558ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 138658ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 138758ae9c530247668f8af36e30d228c716c226b3d4James Dong} 138858ae9c530247668f8af36e30d228c716c226b3d4James Dong 138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 139020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 139120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1392bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 139425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1397a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1398a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1399eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1400bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1401c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1402956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1403be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1404c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1405c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1406c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)), 1407c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)), 1408c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1409c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 1410c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 141225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1413548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 141413f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 141513f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 141619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 14178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 14181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 14191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 14201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 14211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 14221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 14231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 14241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1425c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1426c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1427c059860c73678a202bfa33062723e8f82fb779d9James Dong 14281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 14291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1430c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1431c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 1432c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 1433c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1434c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 14351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 143678a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 143778a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 143878a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 143978a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1440c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1441c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1442c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1443c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 144478a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 144578a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 144678a1a286f736888ae7af8860b2c424af0d978848James Dong } 14471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 14501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 14511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1452c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(chunkId)); 1453c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(sampleId)); 1454c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(1)); 14551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1458c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 14591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 146279761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 14631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14645a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 1465377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGW("0-duration samples found: %zu", sampleCount); 14665a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1467c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1468c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 14691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1471965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1472965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1473965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1474965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { 1475965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1476965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1477c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1478c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1479965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1480965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1481c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1482c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1483c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1484c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1485c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1486c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1487c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 14881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1490c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 14913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 1492c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1493c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1494c059860c73678a202bfa33062723e8f82fb779d9James Dong 1495c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1496c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1497c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1498c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1499c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1500c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1501c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1502c059860c73678a202bfa33062723e8f82fb779d9James Dong 1503c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1504c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1505c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1506c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1507c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1508c059860c73678a202bfa33062723e8f82fb779d9James Dong 150943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 151019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 151119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 151219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 151319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 151419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 151519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 151619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 151719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 151819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 151919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 152019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 152119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 152219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 152319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 152419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 152519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 152619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 152719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 152819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 152919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 153019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 153119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 153219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 153319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 153419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 153519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 153619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 153719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 153819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 153919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 154019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 154120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 154220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 154320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 154420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 154520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1546c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 1547c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 1548c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 1549c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 1550c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 1551c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 1552c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 1553c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 1554c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 1555c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 1556c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 1557c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 1558c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 1559c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 1560c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 1561c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 156220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 156320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 156420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 156520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 156620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 156720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 156893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 15693856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 157093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 157193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 157293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 157393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 157493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 157593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 1576a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs); 157793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 157893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 157993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 158093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 158193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 158293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 15831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 15841c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 15853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 15861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 15871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 15881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 15891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15911c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 15923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 15931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 15941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 15951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 15971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 15981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 16001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 16011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 16021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 16031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 160643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 16071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1609fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1610a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("writeChunkToFile: %" PRId64 " from %s track", 16115410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video"); 1612fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1613fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1614fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1615fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1616fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1617fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong off64_t offset = chunk->mTrack->isAvc() 1618fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong ? addLengthPrefixedSample_l(*it) 1619fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1620fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1621fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1622fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1623fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 16241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 16271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1628fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 16291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1630fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 16311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1633fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 16343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 16351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 163670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 163770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1638e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 163970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 16401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 164170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 164270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 164370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 16441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 1645377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGD("%zu chunks are written in the last batch", outstandingChunks); 16461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1648fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 16493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 16501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 16521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 16531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 16541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 16551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 16561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 16571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 16581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 16591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 16601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 16653856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 1666fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 16671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 16701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 16711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1672fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 16731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 16741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 16751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1676fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1677fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1678fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 167970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 168070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 168170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 168270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 168370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 168470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 168570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1686fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 16871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1689fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1690fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 16911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16931c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 16943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 16951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1696a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1697fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1698fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 16991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1700fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1701fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1702fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1703fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 17041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 17051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1707de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // In real time recording mode, write without holding the lock in order 1708de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // to reduce the blocking time for media track threads. 1709de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // Otherwise, hold the lock until the existing chunks get written to the 1710de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // file. 1711fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 1712de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1713de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.unlock(); 1714de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1715fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 1716de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1717de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.lock(); 1718de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1719fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 17201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1721fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1722fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 17231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17251c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 17263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 17271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 17291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1730e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 17311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 17321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 17331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 17341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 173570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 173670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 17371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 17381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 17391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 17411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 17421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 17431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 17441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 1745411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 17461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 17471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 175093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1751a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1752a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1753a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1754a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1755a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 175625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 175793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 175819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 175919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 176019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 176170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 176219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 176313f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 176413f6284305e4b27395a23db7882d670bdb1bcae1James Dong if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 176513f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 176613f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 176713f6284305e4b27395a23db7882d670bdb1bcae1James Dong 176893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 176993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1770f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1771de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 1772a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 1773a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 1774a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 1775a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 1776a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 1777a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 177886b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 177986b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 1780a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 178186b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 178286b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 178386b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 178486b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 178586b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 1786a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs); 1787a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 1788a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1789f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1790a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1791f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 179225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 179325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 179425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 179525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 179620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 179720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 179820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 179920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 180020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 180120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1802eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 1803c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 180425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1805956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 18061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 180743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 180820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 180925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 181020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 181125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 181225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 181320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 181420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 181537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1816a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 181737187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1818a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1819a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 182037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 182172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track stopping", mIsAudio? "Audio": "Video"); 1822eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 182329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 1824eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 1825eaae38445a340c4857c1c5569475879a728e63b7James Dong } 1826eaae38445a340c4857c1c5569475879a728e63b7James Dong 182720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 182837187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 182920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 183020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 183120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 183272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track source stopping", mIsAudio? "Audio": "Video"); 183372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mSource->stop(); 183472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track source stopped", mIsAudio? "Audio": "Video"); 183572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 183620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 183720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 1838377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 183937187916a486504acaf83bea30147eb5fbf46ae5James Dong 1840b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%s track stopped", mIsAudio? "Audio": "Video"); 184137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 184220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 184320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 184425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 184525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 184625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 184725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 184920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 185120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 185237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 1853377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT return (void *)(uintptr_t)err; 185420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 185520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 18573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 18583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 18603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 18613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 18643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 18653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 1866a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("findNextStartCode: %p %zu", data, length); 18673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 18693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 18703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 18713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 18723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 18743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 18753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 18773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 18803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 18813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 18833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 18843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 18853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 18873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 18883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 188929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 18903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 18913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 18943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 18953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 189629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 18973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 18983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 19003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 19013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 19023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 19033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 19043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 19063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 190729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 19083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 19093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 19123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 19133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 19163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 19203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 19233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 1925377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 19303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 19363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 19373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 19393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 19403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 19413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 19423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 19433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 19453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 19463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 19473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 19483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 19493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 19503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 19513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 19523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 19533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 195429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 19553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 19583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 19593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 19613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 19623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 196329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 19643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 19673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 19683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 19703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 197129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 19723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 19763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 19803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 19813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 19823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 19833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 19863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 19873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 19883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 198929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 19903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 1994377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 19953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 20003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 20013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 200329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 2007377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 20083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20111374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 20121374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 20131374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 20141374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 20163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 20193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 202029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20241374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 2027548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 202803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 202903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 2030548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 203103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 203229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 203303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 203403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 203503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 2037377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 203803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 203903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 204003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 20423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 204403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 204503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 204703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 204803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 204903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 20513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 205203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 205303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 20543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 20553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 20563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 20573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 205803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2060b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2061b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 2062b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2063b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 2064b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 206503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 20673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 20683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 20693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 20703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 20713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 20723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 20733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 20743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 20753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 20763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 20783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 20793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 20803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 20833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 20843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 20853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 20863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 20873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 20883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 20893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 20903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 20913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 20923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 20943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 20953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 20963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 209703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 209803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 209903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 210003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 2101872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 2102872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 2103872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 2104872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 2105872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 2106872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2107872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 2108872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 2109872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2110872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 2111872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2112872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2113872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2114872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 2115872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2116872a481558350634a3fd5cb67939de288af00ecbJames Dong} 2117872a481558350634a3fd5cb67939de288af00ecbJames Dong 211837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 211930ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 212013aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 212143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 212213aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 212313aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 212413aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 2125965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 2126965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 2127965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 2128965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 2129965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 2130000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 2131a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 2132965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 2133000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 2134000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2135000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 213643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 2138e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2139a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 2140a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 2141a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } else { 2142a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 2143a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 2144de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2145de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2146de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2147de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2148985f838934510983d8a887461e98dca60a6e858fJames Dong 2149d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 215020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 215193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 215220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 215311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih const char *trackName = mIsAudio ? "Audio" : "Video"; 215493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 215520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 215620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 215720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 215813aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 215920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 216020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 216120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2162a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 2163a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 2164a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2165a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2166a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2167a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2168a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2169a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2170a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 217130ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 217230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 217303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 217403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 217503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 2176548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 2177548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 21781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 217903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 218003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 218103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 218203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 218343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_EQ((status_t)OK, err); 21841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 218503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 218603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 218703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 218803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 218903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 219003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 219130ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 219230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 219330ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 219430ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 219530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2196548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 219730ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2198a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2199a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2200d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2201d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2202d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2203d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2204d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2205d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2206d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2207d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2208d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2209d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 22101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 2211e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2212b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 2213b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mIsAvc) { 2214b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2215b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2216b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2217b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2218b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2219b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2220050b28a593350047845a45a14cc5026221ac1620James Dong 2221d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 22221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 22231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 22241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2225d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2226d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2227d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2228d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2229d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2230d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2231d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2232d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2233d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2234050b28a593350047845a45a14cc5026221ac1620James Dong 2235d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2236d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2237d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2238d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2239d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 224170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2242f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2243f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 22448428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 22453c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 224648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2247a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 22488428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 224911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) { 225011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 225111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 225211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 225311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 22548428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 225511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) { 225611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 225711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 225811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 225911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 22608428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2261a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2262a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2263a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2264a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 226511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 226611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 226711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 226811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 226911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2270000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (!mIsAudio) { 2271965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2272965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2273965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2274000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 2275965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 2276965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 2277965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2278965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 2279000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 2280000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 228111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) { 228211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 228311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 228411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 228511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2286965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 2287a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64, 2288000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 2289000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2290000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 2291000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 2292000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 229311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) { 229411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 229511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 229611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 229711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2298c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 229943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 230043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 230143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 230243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 230343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 230443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 230543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 230643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 230743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 230843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 230943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 231043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 231143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 231243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 231343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 2314000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2315000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 2316c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 2317000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2318000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2319000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 2320000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2321000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2322000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2323000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2324000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2325000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2326000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2327965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2328872a481558350634a3fd5cb67939de288af00ecbJames Dong 2329de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2330872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2331872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 2332e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2333e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2334872a481558350634a3fd5cb67939de288af00ecbJames Dong 233511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 233611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 233711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 233811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 233911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2340a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64, 234111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, previousPausedDurationUs); 2342c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2343c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 23443b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 23453b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 23465a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 23475a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 23485a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 23495a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 23505a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 23515a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 23525a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 23535a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2354c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 2355a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGE("timestampUs %" PRId64 " < lastTimestampUs %" PRId64 " for %s track", 235611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih timestampUs, lastTimestampUs, trackName); 235711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2358c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return UNKNOWN_ERROR; 23598c460498c028888c533ab442be12b6d4b669b965James Dong } 23608c460498c028888c533ab442be12b6d4b669b965James Dong 236185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // if the duration is different for this sample, see if it is close enough to the previous 236285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // duration that we can fudge it and use the same value, to avoid filling the stts table 236385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // with lots of near-identical entries. 236485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // "close enough" here means that the current duration needs to be adjusted by less 236585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // than 0.1 milliseconds 236685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { 236785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL 236885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen + (mTimeScale / 2)) / mTimeScale; 236985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (deltaUs > -100 && deltaUs < 100) { 237085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // use previous ticks, and adjust timestamp as if it was actually that number 237185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // of ticks 237285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen currDurationTicks = lastDurationTicks; 237385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen timestampUs += deltaUs; 237485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 237585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 237685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen 2377c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 2378c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 2379c059860c73678a202bfa33062723e8f82fb779d9James Dong 2380a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2381a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2382c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 238379761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2384be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2385be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2386be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2387be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2388965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2389be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2390be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2391c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2392be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2393be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 23948644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2395be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2396a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64, 239711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, lastTimestampUs); 23988644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2399c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 24008644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 240120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2402d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 2403c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 2404d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2405d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 240693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 240793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 240893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 240993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2410faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 241193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 241243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2413c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 241458ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 2415c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2416c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count = (mOwner->use32BitFileOffset() 2417c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 2418c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 2419c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2420c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (count == 0) { 24211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 242258ae9c530247668f8af36e30d228c716c226b3d4James Dong } 242358ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 242458ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 242558ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 242658ae9c530247668f8af36e30d228c716c226b3d4James Dong } 242713aec890216948b0c364f8f92792129d0335f506James Dong 242813aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 242913aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 24301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 24311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 243213aec890216948b0c364f8f92792129d0335f506James Dong } else { 243313aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 243413aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 243513aec890216948b0c364f8f92792129d0335f506James Dong } else { 243643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 243743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 243843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 243943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 244043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 244113aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 244213aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 2443c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 2444c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 2445c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 244613aec890216948b0c364f8f92792129d0335f506James Dong } 24471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 244813aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 244913aec890216948b0c364f8f92792129d0335f506James Dong } 245013aec890216948b0c364f8f92792129d0335f506James Dong } 245113aec890216948b0c364f8f92792129d0335f506James Dong } 245213aec890216948b0c364f8f92792129d0335f506James Dong 245320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 245425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 245545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 2456690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2457f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 245845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2459bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2460be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 246113aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 246243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2463c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(1, mStszTableEntries->count()); 246458ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 24651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 24661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 246713aec890216948b0c364f8f92792129d0335f506James Dong } 246813aec890216948b0c364f8f92792129d0335f506James Dong 2469be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2470be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2471be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2472c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 1) { 24738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 247479761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2475be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2476be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2477be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2478a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2479c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() <= 2) { 248079761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2481a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 248279761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2483a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2484a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 248579761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2486a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2487a472613aec322e25891abf5c77bf3f7e3c244920James Dong 248843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // The last ctts box may not have been written yet, and this 248943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // is to make sure that we write out the last ctts box. 249043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 249143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (cttsSampleCount > 0) { 249243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 249343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 249443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 249543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 2496c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 249725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 249843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 249943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 250043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2501df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 250211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih count, nZeroLengthFrames, mStszTableEntries->count(), trackName); 2503872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2504a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs()); 2505872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2506365a963142093a1cd8efdcea76b5f65096a5b115James Dong 250737187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 250837187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 250937187916a486504acaf83bea30147eb5fbf46ae5James Dong } 251037187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2511365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2512365a963142093a1cd8efdcea76b5f65096a5b115James Dong 251345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 2514c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { // no samples written 251529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 251645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 251745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 251845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2519c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (!mIsAudio && mStssTableEntries->count() == 0) { // no sync frames for video 252029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 252145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 252245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 252345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 252445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 252545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 252645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 252745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 252845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 252945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 253045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 253143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 253207ec01904613a0bac32caaa8444b4690998faed7James Dong 253307ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 253407ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 253507ec01904613a0bac32caaa8444b4690998faed7James Dong return; 253607ec01904613a0bac32caaa8444b4690998faed7James Dong } 253707ec01904613a0bac32caaa8444b4690998faed7James Dong 253843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 253943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 254043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 254143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 254243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mIsAudio? 0: 1); 254343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 254443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 254543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 254643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 254743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 254843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 254943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2550c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 255143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 255286b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 255386b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 255486b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 255586b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 255686b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 255786b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 255886b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 255986b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 256086b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 256186b7f47aa7482424cf8fd248f1315311919be3b0James Dong 256286b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 256370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 256470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 256586b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 256670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 256707ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 256807ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 256907ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 257007ec01904613a0bac32caaa8444b4690998faed7James Dong 257143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 257243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 257343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 257443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 257570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 257670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 257770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 257870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 257970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 258070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 258170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 258270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 258343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 258443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 258543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2586faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 2587a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("trackProgressStatus: %" PRId64 " us", timeUs); 2588c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2589215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 2590215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 2591a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs); 2592bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 259393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 259493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 259593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 259693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2597faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 2598bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 2599faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 2600bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 2601faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2602faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 2603faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 2604faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 2605bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2606bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2607faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2608faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 2609faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2610faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2611faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 2612faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 2613bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2614bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2615faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2616faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 2617faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 2618bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2619bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2620faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 2621faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2622faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 2623faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2624d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 2625a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs); 2626e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2627d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 2628e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2629e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2630e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 2631a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs); 2632e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2633e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 2634e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2635e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2636de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const { 2637de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui return mIsRealTimeRecording; 2638de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui} 2639de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2640b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 2641b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 2642b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 2643b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 26441c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 26453856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 26461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 26471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 26481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 264913aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 265020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 265120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26523b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 2653c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 265420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 265520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2656d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2657d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 2658d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 2659d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2660690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 2661690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 2662690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2663690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2664690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2665690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2666690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2667690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 266829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 2669690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2670690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2671690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2672690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2673690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 267429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 2675690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2676690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2677690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2678690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2679690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2680690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 268220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s track time scale: %d", 26841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 26858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 2686efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2698b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 2707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 2714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 2716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 2717965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong writeCttsBox(); 2718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mIsAudio) { 2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 2720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mp4v"); 2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("s263"); 2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avc1"); 2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 273829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 2762c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->writeInt8(0); // compressor string length 2763c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->write(" ", 31); 2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 276743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(23 + mCodecSpecificDataSize, 128); 2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *fourcc = NULL; 2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "samr"; 2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "sawb"; 2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "mp4a"; 2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 279329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 2812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 282643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 282943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(mCodecSpecificDataSize + 23, 128); 2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2844ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier int32_t bitRate; 2845ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier bool success = mMeta->findInt32(kKeyBitRate, &bitRate); 2846ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier mOwner->writeInt32(success ? bitRate : 96000); // max bit rate 2847ebada74ec20c6bd46e81d2f4c160ac176c10784dDaniel Bonnevier mOwner->writeInt32(success ? bitRate : 96000); // avg bit rate 2848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2853b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2863b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 2864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 286543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 2873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 2874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 2879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 2881b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 0x77, 0x00, 2882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00, 2883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00 2884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 2886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2902efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 2903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 2904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 2907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2909219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 2910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 29118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 2912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 2914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2916b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 292420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 2931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 2938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 2942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 2943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2948b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 2960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 2962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 2967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2971efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 2972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 2973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 2978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 2979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 2980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 2982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 2983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 2984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 2985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // language code 2986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 2991b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 2992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 2993b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 3006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 3010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 3011b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 3013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 3014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 3015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 3018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 3019b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 3020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 3021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3023b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 3024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 302543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mCodecSpecificDataSize, 5); 3026b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 3028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 3029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 3030b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 3031b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 3032b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 3033b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3036b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 3037b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 3038b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 3039b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 3040b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 3041b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 3042b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 3043b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3044b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3045b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 3046b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 3047b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 3048b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 3049b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 3050b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 3051b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3052b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3053000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 3054a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 3055b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3056b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 305743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 3058b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3060000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 3061000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 3062000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3063000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 3064000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 3065000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3066c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3067c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mSttsTableEntries->get(duration, 1)); 3068c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back to host byte order 3069c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 3070c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 3071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 307320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3074965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 3075965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { // ctts is not for audio 3076965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3077965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3078965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3079000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 3080000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 3081000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 3082000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 3083000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3084965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 3085c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 3086965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3087965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3088965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3089a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]", 3090c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 3091965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3092965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 3093000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3094c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3095c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCttsTableEntries->get(duration, 1)); 3096c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back host byte order 3097c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1); 3098c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 3099965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 3100965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 3101965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3102b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 3103b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 3104b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 3106b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 3107b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 310825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 3109b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 3110b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 3111b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3112c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 3113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 3114b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 3115b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 311620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3117b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 3118b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 3119b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 3121b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 3122b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 312320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3124b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 3125b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 3126b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 3128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 3129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 3130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 3131b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3132b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 313320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 313420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 313507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 313607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 313707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 313807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 313907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 314007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 3141e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeHdlr() { 3142e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("hdlr"); 3143e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3144e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Predefined 3145e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3146e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[0] 3147e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[1] 3148e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Reserved[2] 3149e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt8(0); // Name (empty) 3150e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3151e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3152e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3153e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeKeys() { 3154e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3155e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3156e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("keys"); 3157e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); // Version, Flags 3158e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(count); // Entry_count 3159e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3160e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3161e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3162e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t n = strlen(key); 3163e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(n + 8); 3164e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeFourcc("mdta"); 3165e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang write(key, n); // write without the \0 3166e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3167e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3168e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3169e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3170e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeIlst() { 3171e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3172e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3173e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("ilst"); 3174e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang for (size_t i = 0; i < count; i++) { 3175e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox(i + 1); // key id (1-based) 3176e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("data"); 3177e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang AMessage::Type type; 3178e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang const char *key = mMetaKeys->getEntryNameAt(i, &type); 3179e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang switch (type) { 31807c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang case AMessage::kTypeString: 31817c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang { 31827c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang AString val; 31837c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang CHECK(mMetaKeys->findString(key, &val)); 31847c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(1); // type = UTF8 31857c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 31867c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang write(val.c_str(), strlen(val.c_str())); // write without \0 31877c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang break; 31887c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang } 31897c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang 3190e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeFloat: 3191e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3192e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang float val; 3193e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findFloat(key, &val)); 31947c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(23); // type = float32 31957c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3196e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(*reinterpret_cast<int32_t *>(&val)); 3197e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3198e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3199e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3200e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang case AMessage::kTypeInt32: 3201e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3202e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang int32_t val; 3203e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang CHECK(mMetaKeys->findInt32(key, &val)); 32047c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(67); // type = signed int32 32057c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3206e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(val); 3207e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3208e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3209e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3210e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang default: 3211e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang { 3212e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang ALOGW("Unsupported key type, writing 0 instead"); 32137c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(77); // type = unsigned int32 32147c4820d23b68f748b8dfff3d4bb5b13e9d4811a8Chong Zhang writeInt32(0); // default country/language 3215e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeInt32(0); 3216e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang break; 3217e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3218e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3219e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // data 3220e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // key id 3221e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3222e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); // ilst 3223e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3224e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3225e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhangvoid MPEG4Writer::writeMetaBox() { 3226e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang size_t count = mMetaKeys->countEntries(); 3227e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang if (count == 0) { 3228e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang return; 3229e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang } 3230e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 3231e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang beginBox("meta"); 3232e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeHdlr(); 3233e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeKeys(); 3234e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang writeIlst(); 3235e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang endBox(); 3236e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang} 3237e76dba7af9589d9ed7b116eec3a74168a8352925Chong Zhang 323807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 323907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 324007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 324107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 324207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 324307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 324407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 324507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 324607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 3247432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 3248432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 324907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 325007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 325107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 325207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 325307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 325407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 325507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 325607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 325720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3258