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> 3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 3518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 3603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h> 3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 39d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h> 4007ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h> 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h" 4319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 44dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn 45dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#ifndef __predict_false 46dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#define __predict_false(exp) __builtin_expect((exp) != 0, 0) 47dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn#endif 48dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn 4911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih#define WARN_UNLESS(condition, message, ...) \ 50dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn( (__predict_false(condition)) ? false : ({ \ 5111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih ALOGW("Condition %s failed " message, #condition, ##__VA_ARGS__); \ 5211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih true; \ 5311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih})) 5411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5777e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024; 581f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32 591f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad // filesystem file size 601f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad // used by most SD cards 613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07; 623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08; 6370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs = 700000LL; 645b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 67bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId); 688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 7237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t stop(); 7337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 7425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 763b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 77d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 78b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTrackHeader(bool use32BitOffset = true); 791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 83c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong void addChunkOffset(off64_t offset); 8470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int32_t getTrackId() const { return mTrackId; } 85dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 88000e18370baae60ffd9f25b509501dd8c26deabfJames Dong enum { 89000e18370baae60ffd9f25b509501dd8c26deabfJames Dong kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 908c460498c028888c533ab442be12b6d4b669b965James Dong kSampleArraySize = 1000, 91000e18370baae60ffd9f25b509501dd8c26deabfJames Dong }; 92000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 93c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // A helper class to handle faster write box with table entries 94c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong template<class TYPE> 95c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong struct ListTableEntries { 96c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity) 97c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mElementCapacity(elementCapacity), 98c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEntryCapacity(entryCapacity), 99c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTotalNumTableEntries(0), 100c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry(0), 101c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement(NULL) { 102c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mElementCapacity, 0); 103c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mEntryCapacity, 0); 104c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 106c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Free the allocated memory. 107c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ~ListTableEntries() { 108c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (!mTableEntryList.empty()) { 109c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 110c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete[] (*it); 111c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.erase(it); 112c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 114c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 115c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Replace the value at the given position by the given value. 116c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // There must be an existing value at the given position. 117c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order 118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void set(const TYPE& value, uint32_t pos) { 12025f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity); 121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value; 132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Get the value at the given position by the given value. 135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value the retrieved value at the position in network byte order. 136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @return true if a value is found. 138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool get(TYPE& value, uint32_t pos) const { 13925f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong if (pos >= mTotalNumTableEntries * mEntryCapacity) { 140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return false; 141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong value = (*it)[(pos % (mElementCapacity * mEntryCapacity))]; 153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return true; 154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Store a single value. 157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order. 158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void add(const TYPE& value) { 159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nValues = mNumValuesInCurrEntry % mEntryCapacity; 162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries == 0 && nValues == 0) { 163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity]; 164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCurrTableEntriesElement != NULL); 165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.push_back(mCurrTableEntriesElement); 166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t pos = nEntries * mEntryCapacity + nValues; 169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement[pos] = value; 170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mNumValuesInCurrEntry; 172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) { 173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mTotalNumTableEntries; 174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry = 0; 175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Write out the table entries: 179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 1. the number of entries goes first 180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 2. followed by the values in the table enties in order 181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg writer the writer to actual write to the storage 182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void write(MPEG4Writer *writer) const { 183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0); 184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries; 185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->writeInt32(nEntries); 186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong it != mTableEntryList.end(); ++it) { 188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(nEntries, 0); 189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries >= mElementCapacity) { 190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity); 191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong nEntries -= mElementCapacity; 192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries); 194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong break; 195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Return the number of entries in the table. 200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count() const { return mTotalNumTableEntries; } 201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong private: 203c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mElementCapacity; // # entries in an element 204c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mEntryCapacity; // # of values in each entry 205c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mTotalNumTableEntries; 206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mNumValuesInCurrEntry; // up to mEntryCapacity 207c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong TYPE *mCurrTableEntriesElement; 208c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mutable List<TYPE *> mTableEntryList; 209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong }; 212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 217693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 219a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 220a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 221eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 2221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 2231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 2241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 225bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 226c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 22743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 228e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 229d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 2301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 2318f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 235be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 23613aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 2371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool mSamplesHaveSameSize; 239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStszTableEntries; 240be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStcoTableEntries; 242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<off64_t> *mCo64TableEntries; 243c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStscTableEntries; 244c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStssTableEntries; 245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mSttsTableEntries; 246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mCttsTableEntries; 247965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 248000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMinCttsOffsetTimeUs; 249000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMaxCttsOffsetTimeUs; 250965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 2523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 2533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 2543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 2553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 2563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 2573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 2583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 2593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 2603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 2613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 2623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 2633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 2643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 267548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 26893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 2713c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 27270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 27370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 27493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 27593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 27625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 277872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 278872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 279872a481558350634a3fd5cb67939de288af00ecbJames Dong 280000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int32_t getStartTimeOffsetScaledTime() const; 281000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 28337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 2863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 2873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 288b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 289b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 290b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 291215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 292215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 293faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 29493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 29503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 29619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 29719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 298c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 299c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 300c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 301c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 302c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 303c059860c73678a202bfa33062723e8f82fb779d9James Dong 304690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 305690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 30613f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t mRotation; 307690f546b0ee548dbfe997df36418e5302ec2d786James Dong 3081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 3091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 3101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 31179761ab096f57c3027fad9556c2bc436672d614eJames Dong 31279761ab096f57c3027fad9556c2bc436672d614eJames Dong // Duration is time scale based 31379761ab096f57c3027fad9556c2bc436672d614eJames Dong void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 314965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 31545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 31645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong bool isTrackMalFormed() const; 31743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 3181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 319b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 324b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 325965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void writeCttsBox(); 326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 333efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeMdhdBox(uint32_t now); 334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 337efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeTkhdBox(uint32_t now); 338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 34620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 34820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 349674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(-1), 350674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(NO_INIT), 351de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording(true), 352b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 3531acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 354a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 355a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 356a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 357411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 35913aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 3607837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 36107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 36207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 36307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 36486b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 36586b7f47aa7482424cf8fd248f1315311919be3b0James Dong mStartTimeOffsetMs(-1) { 366674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong 367af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); 368674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mFd >= 0) { 369674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck = OK; 370674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong } 37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37330ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 374674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(dup(fd)), 375674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(mFd < 0? NO_INIT: OK), 376de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording(true), 377b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 3781acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 379a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 380a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 381a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 382411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 38330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 38413aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 3857837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 38607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 38707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 38807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 38986b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 39086b7f47aa7482424cf8fd248f1315311919be3b0James Dong mStartTimeOffsetMs(-1) { 39130ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 39230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 39320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 3948bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong reset(); 39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 3971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 3991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 4001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 405dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 406dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 407dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 408dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 409dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 410dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 411dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 412dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 413dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 414dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 415dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 416dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 417dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 418dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 419dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 420dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 421dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 422dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 42384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber int fd, const Vector<String16>& /* args */) const { 424dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 425dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 426dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 427dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 428dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 429dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 430dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 431dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 432c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 43313210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 434377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); 43513210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 436dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 437dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 438dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 439dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 4402dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 441bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 442bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 44329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Attempt to add source AFTER recording is started"); 444bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 445bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 446acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 447acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // At most 2 tracks can be supported. 448acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.size() >= 2) { 449a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGE("Too many tracks (%zu) to add", mTracks.size()); 450acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 451acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 452acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 453acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong CHECK(source.get() != NULL); 454acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 455acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // A track of type other than video or audio is not supported. 456acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong const char *mime; 457acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong source->getFormat()->findCString(kKeyMIMEType, &mime); 458acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong bool isAudio = !strncasecmp(mime, "audio/", 6); 459acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong bool isVideo = !strncasecmp(mime, "video/", 6); 460acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (!isAudio && !isVideo) { 461acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("Track (%s) other than video or audio is not supported", 462acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong mime); 463acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 464acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 465acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 466acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // At this point, we know the track to be added is either 467acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // video or audio. Thus, we only need to check whether it 468acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // is an audio track or not (if it is not, then it must be 469acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // a video track). 470acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 471acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // No more than one video or one audio track is supported. 472acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong for (List<Track*>::iterator it = mTracks.begin(); 473acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong it != mTracks.end(); ++it) { 474acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if ((*it)->isAudio() == isAudio) { 475acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("%s track already exists", isAudio? "Audio": "Video"); 476acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 477acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 478acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 479acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 480acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // This is the first track of either audio or video. 481acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // Go ahead to add the track. 482219f195159f93d627af2b243732e3f9020511a46James Dong Track *track = new Track(this, source, 1 + mTracks.size()); 48320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 4842dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 4852dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 48620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 48720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 48893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 489acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.empty()) { 490acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("No source added"); 491acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return INVALID_OPERATION; 492acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 493acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 494a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 495a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 49693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 497a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 498a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 499a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 500a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 501a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 502a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 503a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 504a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 505a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 506a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 507a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 508a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 509a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 5102dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 5112dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 5122dec2b5be2056c6d9428897dc672185872d30d17James Dong // 5132dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 5142dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 5152dec2b5be2056c6d9428897dc672185872d30d17James Dong 51678a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 5172dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 51878a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 5192dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 5202dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 5212dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 5222dec2b5be2056c6d9428897dc672185872d30d17James Dong 5232dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 5242dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 5252dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 52678a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 5272dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 5282dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 5292dec2b5be2056c6d9428897dc672185872d30d17James Dong 53078a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 531a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 53278a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 53378a1a286f736888ae7af8860b2c424af0d978848James Dong } 53478a1a286f736888ae7af8860b2c424af0d978848James Dong 53578a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 53678a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 53778a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 53878a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 53978a1a286f736888ae7af8860b2c424af0d978848James Dong ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000); 54078a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 54178a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 54278a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 54378a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 54478a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 54578a1a286f736888ae7af8860b2c424af0d978848James Dong } 54678a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 54778a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 54878a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 54978a1a286f736888ae7af8860b2c424af0d978848James Dong } 5502dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5512dec2b5be2056c6d9428897dc672185872d30d17James Dong } 55278a1a286f736888ae7af8860b2c424af0d978848James Dong 5532dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 5542dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 5552dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5562dec2b5be2056c6d9428897dc672185872d30d17James Dong 5572dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 5582dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 5592dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 5602dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 5612dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5622dec2b5be2056c6d9428897dc672185872d30d17James Dong 563a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the" 564a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn " estimated moov size %" PRId64 " bytes", 5652dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 5662dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 5672dec2b5be2056c6d9428897dc672185872d30d17James Dong} 5682dec2b5be2056c6d9428897dc672185872d30d17James Dong 5692dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 570674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 57125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 574a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 575a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 576a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 577a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 578a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 579a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 580a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 581a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 582a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 583a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 5842dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 5852dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 5862dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 5872dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 5882dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 5892dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5902dec2b5be2056c6d9428897dc672185872d30d17James Dong 5911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 5921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 5931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 5941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 5951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 5961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 5971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 5981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 5991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 600a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. " 601a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn "It is changed to %" PRId64 " bytes", 602d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 603d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 6041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 6061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 607b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 608b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 609b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 610b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 611b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 6122dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6132dec2b5be2056c6d9428897dc672185872d30d17James Dong 614de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui int32_t isRealTimeRecording; 615de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) { 616de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording = isRealTimeRecording; 617de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 618de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 619065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 62093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 621a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 622a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 623a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 62493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 625a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 626a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 627a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 628a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 6298f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 6308f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 6318f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 6328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 63343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 6343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("movie time scale: %d", mTimeScale); 6358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 63677e8ae9967a078770416619e99ddb5b010def312James Dong /* 63777e8ae9967a078770416619e99ddb5b010def312James Dong * When the requested file size limit is small, the priority 63877e8ae9967a078770416619e99ddb5b010def312James Dong * is to meet the file size limit requirement, rather than 6397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to make the file streamable. mStreamableFile does not tell 6407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * whether the actual recorded file is streamable or not. 64177e8ae9967a078770416619e99ddb5b010def312James Dong */ 64277e8ae9967a078770416619e99ddb5b010def312James Dong mStreamableFile = 64377e8ae9967a078770416619e99ddb5b010def312James Dong (mMaxFileSizeLimitBytes != 0 && 64477e8ae9967a078770416619e99ddb5b010def312James Dong mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 64577e8ae9967a078770416619e99ddb5b010def312James Dong 6467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong /* 6477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory is true if the amount of data in moov box is 6487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * smaller than the reserved free space at the beginning of a file, AND 6497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * when the content of moov box is constructed. Note that video/audio 6507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * frame data is always written to the file but not in the memory. 6517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6527b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Before stop()/reset() is called, mWriteMoovBoxToMemory is always 6537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * false. When reset() is called at the end of a recording session, 6547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Moov box needs to be constructed. 6557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory 6577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to set to mStreamableFile so that if 6587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the file is intended to be streamable, it is set to true; 6597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * otherwise, it is set to false. When the value is set to false, 6607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * all the content of the moov box is written immediately to 6617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the end of the file. When the value is set to true, all the 6627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * content of the moov box is written to an in-memory cache, 6637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mMoovBoxBuffer, util the following condition happens. Note 6647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * that the size of the in-memory cache is the same as the 6657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * reserved free space at the beginning of the file. 6667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 2) While the data of the moov box is written to an in-memory 6687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache, the data size is checked against the reserved space. 6697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * If the data size surpasses the reserved space, subsequent moov 6707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * data could no longer be hold in the in-memory cache. This also 6717b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * indicates that the reserved space was too small. At this point, 6727b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * _all_ moov data must be written to the end of the file. 6737b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory must be set to false to direct the write 6747b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to the file. 6757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6767b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 3) If the data size in moov box is smaller than the reserved 6777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space after moov box is completely constructed, the in-memory 6787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache copy of the moov box is written to the reserved free 6797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space. Thus, immediately after the moov is completedly 6807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * constructed, mWriteMoovBoxToMemory is always set to false. 6817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong */ 6827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 6837837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 6847837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 6857837c17063a4c50bc856ba59418516fdab731de7James Dong 686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6887837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6907837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 6912dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 6922dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 6932dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 6942dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6952dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 6967837c17063a4c50bc856ba59418516fdab731de7James Dong } 69743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mEstimatedMoovBoxSize, 8); 69877e8ae9967a078770416619e99ddb5b010def312James Dong if (mStreamableFile) { 69977e8ae9967a078770416619e99ddb5b010def312James Dong // Reserve a 'free' box only for streamable file 70077e8ae9967a078770416619e99ddb5b010def312James Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 70177e8ae9967a078770416619e99ddb5b010def312James Dong writeInt32(mEstimatedMoovBoxSize); 70277e8ae9967a078770416619e99ddb5b010def312James Dong write("free", 4); 70377e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 70477e8ae9967a078770416619e99ddb5b010def312James Dong } else { 70577e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mOffset; 70677e8ae9967a078770416619e99ddb5b010def312James Dong } 7077837c17063a4c50bc856ba59418516fdab731de7James Dong 7087837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 709c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 7101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 7111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 7121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 7131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 7141acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 7151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 7171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 7181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 7191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 7201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 722a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 723a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 7251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 726a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 72725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 7311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 7321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 7331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 73437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 735674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 73637187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 737a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 738a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 73937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 740a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 741a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 74237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 74337187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 74437187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 74537187916a486504acaf83bea30147eb5fbf46ae5James Dong } 746a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 74737187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 748a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 749a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 7501c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 751b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping writer thread"); 752411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 753411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 754411ba422e3635d534928ffd81abf54f4f291c739James Dong } 7551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 7571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 7581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 7601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 7611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 7621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 7641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 765411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 766b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Writer thread stopped"); 7671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 7681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 76913f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 77013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 77113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 77213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 77313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 77413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 77513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 77613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 77713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 77813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 77913f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 78013f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 7813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeCompositionMatrix"); 78213f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 78313f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 78413f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 78513f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 78613f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 78713f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 78813f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 78913f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 79013f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 79113f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 79213f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 79313f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 79413f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 79513f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 79613f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 79713f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 79813f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 79913f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 80013f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 80113f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 80213f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 80313f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 80413f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 80513f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 80613f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 80713f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 80813f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 80913f6284305e4b27395a23db7882d670bdb1bcae1James Dong 81013f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 81113f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 81213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 81313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 81413f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 81513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 81613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 81713f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 81813f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 81913f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 82013f6284305e4b27395a23db7882d670bdb1bcae1James Dong 821411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 822411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 823411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 824411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 825411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 826411ba422e3635d534928ffd81abf54f4f291c739James Dong} 82713f6284305e4b27395a23db7882d670bdb1bcae1James Dong 8288bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() { 829674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 83037187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 831411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 832411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 833411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 834411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 835411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 836411ba422e3635d534928ffd81abf54f4f291c739James Dong } 837411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 838411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 839411ba422e3635d534928ffd81abf54f4f291c739James Dong } 84020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 84237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 8438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 84465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 84520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 84620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 84737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 84837187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 84937187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 85037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8528f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 8538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 8548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 85665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 85765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 85865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 85965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 86065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 86165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 862a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGD("Duration from tracks range is [%" PRId64 ", %" PRId64 "] us", 86365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 86420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 86520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 8677837c17063a4c50bc856ba59418516fdab731de7James Dong 86837187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 86937187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 870411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 87137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 87237187916a486504acaf83bea30147eb5fbf46ae5James Dong } 87337187916a486504acaf83bea30147eb5fbf46ae5James Dong 87420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 8751acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 876c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 8771f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); 878c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 8791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 880c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 8811f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint64_t size = mOffset - mMdatOffset; 8821acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 883c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 8841acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 885c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 88620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Construct moov box now 8887837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 8897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = mStreamableFile; 8907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 8917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // There is no need to allocate in-memory cache 8927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // for moov box if the file is not streamable. 8937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 8947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 8957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong CHECK(mMoovBoxBuffer != NULL); 8967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 89820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8997b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // mWriteMoovBoxToMemory could be set to false in 9007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // MPEG4Writer::write() method 9017b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 9027b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 9037b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Content of the moov box is saved in the cache, and the in-memory 9047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // moov box needs to be written to the file in a single shot. 9057b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 90643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 9077837c17063a4c50bc856ba59418516fdab731de7James Dong 9087837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 909c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 9107837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 911674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 9127837c17063a4c50bc856ba59418516fdab731de7James Dong 9137837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 914c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 9157837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 9167837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 9177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } else { 9187b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ALOGI("The mp4 file will not be streamable."); 9197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 9207837c17063a4c50bc856ba59418516fdab731de7James Dong 9217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Free in-memory cache for moov box 9227b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mMoovBoxBuffer != NULL) { 9237837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 9247837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 9257837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 9267837c17063a4c50bc856ba59418516fdab731de7James Dong } 9277837c17063a4c50bc856ba59418516fdab731de7James Dong 9280c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 92920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 930411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 93137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 93320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 934efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() { 935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 936efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 937efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // while time function returns Unix epoch values which starts 938efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // at 1970-01-01. Lets add the number of seconds between them 939efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60); 940efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson return mpeg4Time; 941efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson} 942efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson 943efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 944efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 948b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 97107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 97207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 97307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 9822cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 9898284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 9908284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("isom"); 9918284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("3gp4"); 992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 9938284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 9948284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 9968284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 1000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 1001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 100207ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 100307ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 100407ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 100507ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 100607ec01904613a0bac32caaa8444b4690998faed7James Dong 100707ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 100807ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 100907ec01904613a0bac32caaa8444b4690998faed7James Dong char value[PROPERTY_VALUE_MAX]; 101007ec01904613a0bac32caaa8444b4690998faed7James Dong if (property_get("rw.media.record.test", value, NULL) && 101107ec01904613a0bac32caaa8444b4690998faed7James Dong (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 101207ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 101307ec01904613a0bac32caaa8444b4690998faed7James Dong } 101407ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 101507ec01904613a0bac32caaa8444b4690998faed7James Dong} 101607ec01904613a0bac32caaa8444b4690998faed7James Dong 101770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 101807ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 101907ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 102007ec01904613a0bac32caaa8444b4690998faed7James Dong return; 102107ec01904613a0bac32caaa8444b4690998faed7James Dong } 102207ec01904613a0bac32caaa8444b4690998faed7James Dong 102370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 102470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 102570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 102670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 102770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 102870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 102970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 103070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 103170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 103213aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 103313aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 103413aec890216948b0c364f8f92792129d0335f506James Dong return OK; 103513aec890216948b0c364f8f92792129d0335f506James Dong} 103613aec890216948b0c364f8f92792129d0335f506James Dong 103713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 103813aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 103913aec890216948b0c364f8f92792129d0335f506James Dong} 104013aec890216948b0c364f8f92792129d0335f506James Dong 104113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 104213aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 104313aec890216948b0c364f8f92792129d0335f506James Dong} 104420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1045c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 1046c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 104720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1048c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1049c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1050c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 105120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 105220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 105320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 105420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 105703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 105803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 105903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 106003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 106103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 106203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 106303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 106403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 106503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 106603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 106703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 106803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 106903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 107003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1071c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 1072c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 107330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 107430ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 107503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1076b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 1077b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 1078c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1079b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 1080c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1081b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 1082c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1083b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1084c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1085c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 1086c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1087c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1088c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 1089b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1090b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 1091b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 109243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(length, 65536); 109330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1094b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 1095c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1096b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1097c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1098c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1099b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 1100b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 110130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 110230ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 110330ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 110430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 11057837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 1106674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 11077837c17063a4c50bc856ba59418516fdab731de7James Dong 11087837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 11097837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 11107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 1111c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 11121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 11137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // The reserved moov box at the beginning of the file 11147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // is not big enough. Moov box should be written to 11157b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the end of the file from now on, but not to the 11167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // in-memory cache. 11177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 11187b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // We write partial moov box that is in the memory to 11197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the file first. 1120c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 11217837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 11227837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 11237837c17063a4c50bc856ba59418516fdab731de7James Dong } 1124674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 1125674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 11267b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ::write(mFd, ptr, bytes); 11277837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 11287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 11297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // All subsequent moov box content will be written 11307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // to the end of the file. 11317837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 11327837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 11337837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 11347837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 11357837c17063a4c50bc856ba59418516fdab731de7James Dong } 11367837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1137674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 11387837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 11397837c17063a4c50bc856ba59418516fdab731de7James Dong } 11407837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 11417837c17063a4c50bc856ba59418516fdab731de7James Dong} 11427837c17063a4c50bc856ba59418516fdab731de7James Dong 114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 11440c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 114520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11467837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 11477837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 114820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 114920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 115020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 115120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 115220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 11540c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 115520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1156c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 115720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 115820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11597837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 11607837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 11617837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 11627837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1163c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 11647837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 11657837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1166c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 11677837c17063a4c50bc856ba59418516fdab731de7James Dong } 116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1171674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1176674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1181674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1186674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1191674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 11950c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 1196674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 120007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 120107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 120207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 120307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 120407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 120507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 120607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 120707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 120807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 120907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 121007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 121107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 121207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 121307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 121407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 121507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 121607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 121707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 121807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 121907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 122007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 122107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 122207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 122307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 122407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 122507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 122607b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 122707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 122807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 122907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 123007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 123107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 123207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 123307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 123407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 123507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 123607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 123707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 123807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 123907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 124007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 124107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 124207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 124307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 124407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 124507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 124607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 124707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 124807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 124907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 125007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 125107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 125207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 125307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 125407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 125507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 125607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 125707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 125807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 125907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 126007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 126107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 126207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 126307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 126407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 126507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 126607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 126707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 126807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 126907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1271674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 127220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 127320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 127478a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 127578a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 127678a1a286f736888ae7af8860b2c424af0d978848James Dong} 127778a1a286f736888ae7af8860b2c424af0d978848James Dong 1278d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1279d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1280d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1281d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1282d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1283d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1284956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1285d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1286d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1287d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1288d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 12891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 129077e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 129177e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 129277e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 129377e8ae9967a078770416619e99ddb5b010def312James Dong } 1294acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1295acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1296acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1297acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1298d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1299d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1300d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1301d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1302d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1303d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1304d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1305d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1306d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1307d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1308d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1309d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1310d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1311d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1312d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1313d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1314d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 131525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 131625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 131725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 131825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 131925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 132025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 132125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 132225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 132325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 132425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 132525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 132625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 132725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1328f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1329a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("setStartTimestampUs: %" PRId64, timeUs); 133043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 13313c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1332065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1333f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1334a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Earliest track starting time: %" PRId64, mStartTimestampUs); 13353c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 13363c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 13373c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1338f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 13393c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 13403c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 13413c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 13423c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 134358ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 134458ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 134558ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 134658ae9c530247668f8af36e30d228c716c226b3d4James Dong} 134758ae9c530247668f8af36e30d228c716c226b3d4James Dong 134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1351bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 135325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1356a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1357a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1358eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1359bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1360c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1361956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1362be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1363c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1364c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1365c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)), 1366c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)), 1367c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1368c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 1369c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 137125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1372548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 137313f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 137413f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 137519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 13768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 13771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 13781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 13791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 13801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 13811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 13821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 13831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1384c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1385c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1386c059860c73678a202bfa33062723e8f82fb779d9James Dong 13871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 13881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1389c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1390c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 1391c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 1392c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1393c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 13941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 139578a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 139678a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 139778a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 139878a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1399c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1400c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1401c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1402c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 140378a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 140478a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 140578a1a286f736888ae7af8860b2c424af0d978848James Dong } 14061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 14091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 14101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1411c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(chunkId)); 1412c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(sampleId)); 1413c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(1)); 14141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1417c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 14181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 142179761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 14221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14235a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 1424377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGW("0-duration samples found: %zu", sampleCount); 14255a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1426c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1427c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 14281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1430965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1431965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1432965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1433965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { 1434965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1435965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1436c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1437c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1438965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1439965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1440c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1441c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1442c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1443c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1444c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1445c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1446c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 14471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1449c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 14503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 1451c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1452c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1453c059860c73678a202bfa33062723e8f82fb779d9James Dong 1454c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1455c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1456c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1457c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1458c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1459c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1460c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1461c059860c73678a202bfa33062723e8f82fb779d9James Dong 1462c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1463c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1464c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1465c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1466c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1467c059860c73678a202bfa33062723e8f82fb779d9James Dong 146843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 146919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 147019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 147119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 147219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 147319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 147419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 147519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 147619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 147719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 147819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 147919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 148019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 148119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 148219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 148319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 148419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 148519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 148619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 148719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 148819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 148919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 149019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 149119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 149219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 149319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 149419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 149519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 149619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 149719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 149819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 149919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 150020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 150220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 150420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1505c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 1506c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 1507c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 1508c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 1509c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 1510c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 1511c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 1512c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 1513c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 1514c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 1515c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 1516c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 1517c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 1518c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 1519c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 1520c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 152793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 15283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 152993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 153093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 153193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 153293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 153393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 153493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 1535a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Receive request to track progress status for every %" PRId64 " us", timeUs); 153693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 153793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 153893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 153993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 154093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 154193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 15421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 15431c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 15443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 15451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 15461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 15471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 15481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15501c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 15513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 15521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 15531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 15541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 15561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 15571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 15591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 15601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 15611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 15621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 156543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 15661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1568fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1569a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("writeChunkToFile: %" PRId64 " from %s track", 15705410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video"); 1571fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1572fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1573fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1574fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1575fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1576fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong off64_t offset = chunk->mTrack->isAvc() 1577fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong ? addLengthPrefixedSample_l(*it) 1578fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1579fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1580fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1581fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1582fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 15831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 15861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1587fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 15881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1589fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 15901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1592fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 15933856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 15941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 159570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 159670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1597e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 159870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 15991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 160070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 160170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 160270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 16031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 1604377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGD("%zu chunks are written in the last batch", outstandingChunks); 16051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1607fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 16083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 16091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 16111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 16121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 16131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 16141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 16151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 16161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 16171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 16181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 16191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 16243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 1625fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 16261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 16291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 16301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1631fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 16321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 16331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 16341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1635fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1636fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1637fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 163870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 163970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 164070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 164170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 164270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 164370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 164470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1645fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 16461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1648fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1649fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 16501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16521c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 16533856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 16541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1655a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1656fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1657fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 16581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1659fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1660fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1661fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1662fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 16631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 16641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1666de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // In real time recording mode, write without holding the lock in order 1667de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // to reduce the blocking time for media track threads. 1668de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // Otherwise, hold the lock until the existing chunks get written to the 1669de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // file. 1670fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 1671de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1672de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.unlock(); 1673de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1674fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 1675de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1676de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.lock(); 1677de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1678fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 16791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1680fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1681fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 16821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16841c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 16853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 16861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 16881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1689e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 16901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 16911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 16921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 16931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 169470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 169570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 16961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 16971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 17001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 17011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 17021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 17031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 1704411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 17051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 17061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 17071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 170993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1710a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1711a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1712a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1713a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1714a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 171525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 171693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 171719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 171819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 171919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 172070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 172119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 172213f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 172313f6284305e4b27395a23db7882d670bdb1bcae1James Dong if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 172413f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 172513f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 172613f6284305e4b27395a23db7882d670bdb1bcae1James Dong 172793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 172893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1729f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1730de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 1731a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 1732a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 1733a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 1734a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 1735a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 1736a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 173786b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 173886b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 1739a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 174086b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 174186b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 174286b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 174386b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 174486b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 1745a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Start time offset: %" PRId64 " us", startTimeOffsetUs); 1746a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 1747a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1748f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1749a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1750f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 175125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 175225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 175325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 175425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 175520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 175620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 175720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 175820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 175920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 176020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1761eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 1762c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 176325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1764956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 17651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 176643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 176720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 176825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 176920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 177025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 177125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 177220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 177320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 177437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1775a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 177637187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1777a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1778a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 177937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 178072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track stopping", mIsAudio? "Audio": "Video"); 1781eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 178229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 1783eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 1784eaae38445a340c4857c1c5569475879a728e63b7James Dong } 1785eaae38445a340c4857c1c5569475879a728e63b7James Dong 178620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 178737187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 178820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 178920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 179020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 179172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track source stopping", mIsAudio? "Audio": "Video"); 179272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mSource->stop(); 179372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track source stopped", mIsAudio? "Audio": "Video"); 179472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 179520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 179620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 1797377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); 179837187916a486504acaf83bea30147eb5fbf46ae5James Dong 1799b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%s track stopped", mIsAudio? "Audio": "Video"); 180037187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 180120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 180220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 180325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 180425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 180525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 180625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 180720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 180820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 180920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 181020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 181137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 1812377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT return (void *)(uintptr_t)err; 181320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 181420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 18163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 18173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 18193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 18203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 18233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 18243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 1825a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("findNextStartCode: %p %zu", data, length); 18263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 18283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 18293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 18303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 18313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 18333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 18343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 18363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 18393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 18403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 18423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 18433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 18443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 18463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 18473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 184829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 18493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 18503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 18533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 18543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 185529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 18563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 18573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 18593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 18603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 18613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 18623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 18633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 18643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 18653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 186629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 18673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 18683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 18713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 18723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 18733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 18753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 18783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 18793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 18803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 18823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 18833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 1884377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 18853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 18893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 18903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 18913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 18923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 18953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 18963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 18983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 18993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 19003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 19013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 19023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 19033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 19043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 19063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 19073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 19083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 19093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 19103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 19113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 19123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 191329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 19203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 192229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 19233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 19293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 193029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 19393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 19403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 19413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 19423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 19453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 19463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 19473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 194829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 19493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 1953377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); 19543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 19593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 19603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 19613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 196229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 19633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 1966377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); 19673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19701374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 19711374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 19721374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 19731374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 19743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 19753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 19763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 19773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 19783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 197929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 19803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 19813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19831374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 19843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 19853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 1986548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 198703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 198803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 1989548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 199003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 199129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 199203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 199303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 199403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 1996377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT ALOGE("Codec specific data length too short: %zu", size); 199703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 199803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 199903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 20013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 200303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 200403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 200603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 200703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 200803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 20103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 201103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 201203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 20163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 201703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2019b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2020b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 2021b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2022b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 2023b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 202403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 20273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 20283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 20293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 20303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 20313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 20323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 20333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 20343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 20353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 20373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 20383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 20423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 20443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 20453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 20463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 20473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 20483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 20493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 20503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 20513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 20533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 20543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 20553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 205603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 205703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 205803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 205903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 2060872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 2061872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 2062872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 2063872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 2064872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 2065872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2066872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 2067872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 2068872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2069872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 2070872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2071872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2072872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2073872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 2074872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2075872a481558350634a3fd5cb67939de288af00ecbJames Dong} 2076872a481558350634a3fd5cb67939de288af00ecbJames Dong 207737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 207830ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 207913aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 208043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 208113aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 208213aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 208313aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 2084965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 2085965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 2086965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 2087965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 2088965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 2089000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 2090a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 2091965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 2092000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 2093000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2094000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 209543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2096c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 2097e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2098a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 2099a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 2100a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } else { 2101a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 2102a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 2103de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2104de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2105de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2106de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2107985f838934510983d8a887461e98dca60a6e858fJames Dong 2108d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 210920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 211093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 211120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 211211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih const char *trackName = mIsAudio ? "Audio" : "Video"; 211393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 211420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 211520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 211620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 211713aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 211820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 211920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 212020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2121a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 2122a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 2123a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2124a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2125a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2126a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2127a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2128a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2129a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 213030ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 213130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 213203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 213303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 213403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 2135548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 2136548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 21371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 213803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 213903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 214003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 214103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 214243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_EQ((status_t)OK, err); 21431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 214403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 214503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 214603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 214703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 214803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 214903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 215030ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 215130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 215230ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 215330ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 215430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2155548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 215630ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2157a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2158a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2159d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2160d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2161d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2162d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2163d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2164d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2165d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2166d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2167d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2168d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 21691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 2170e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2171b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 2172b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mIsAvc) { 2173b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2174b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2175b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2176b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2177b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2178b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2179050b28a593350047845a45a14cc5026221ac1620James Dong 2180d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 21811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 21821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 21831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2184d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2185d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2186d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2187d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2188d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2189d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2190d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2191d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2192d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2193050b28a593350047845a45a14cc5026221ac1620James Dong 2194d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2195d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2196d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2197d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2198d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 220070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2201f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2202f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 22038428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 22043c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 220548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2206a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 22078428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 220811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) { 220911f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 221011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 221111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 221211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 22138428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 221411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) { 221511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 221611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 221711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 221811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 22198428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2220a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2221a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2222a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2223a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 222411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 222511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 222611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 222711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 222811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2229000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (!mIsAudio) { 2230965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2231965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2232965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2233000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 2234965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 2235965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 2236965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2237965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 2238000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 2239000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 224011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) { 224111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 224211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 224311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 224411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2245965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 2246a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("decoding time: %" PRId64 " and ctts offset time: %" PRId64, 2247000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 2248000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2249000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 2250000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 2251000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 225211f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) { 225311f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 225411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 225511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 225611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 225843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 225943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 226043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 226143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 226243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 226343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 226443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 226543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 226643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 226743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 226843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 226943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 227043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 227143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 227243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 2273000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2274000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 2275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 2276000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2277000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2278000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 2279000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2280000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2281000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2282000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2283000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2284000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2285000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2286965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2287872a481558350634a3fd5cb67939de288af00ecbJames Dong 2288de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2289872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2290872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 2291e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2292e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2293872a481558350634a3fd5cb67939de288af00ecbJames Dong 229411f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) { 229511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 229611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih return ERROR_MALFORMED; 229711f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih } 229811f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih 2299a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s media time stamp: %" PRId64 " and previous paused duration %" PRId64, 230011f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, previousPausedDurationUs); 2301c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2302c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 23033b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 23043b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 23055a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 23065a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 23075a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 23085a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 23095a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 23105a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 23115a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 23125a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2313c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 2314a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGE("timestampUs %" PRId64 " < lastTimestampUs %" PRId64 " for %s track", 231511f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih timestampUs, lastTimestampUs, trackName); 231611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih copy->release(); 2317c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return UNKNOWN_ERROR; 23188c460498c028888c533ab442be12b6d4b669b965James Dong } 23198c460498c028888c533ab442be12b6d4b669b965James Dong 232085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // if the duration is different for this sample, see if it is close enough to the previous 232185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // duration that we can fudge it and use the same value, to avoid filling the stts table 232285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // with lots of near-identical entries. 232385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // "close enough" here means that the current duration needs to be adjusted by less 232485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // than 0.1 milliseconds 232585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { 232685fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL 232785fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen + (mTimeScale / 2)) / mTimeScale; 232885fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen if (deltaUs > -100 && deltaUs < 100) { 232985fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // use previous ticks, and adjust timestamp as if it was actually that number 233085fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen // of ticks 233185fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen currDurationTicks = lastDurationTicks; 233285fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen timestampUs += deltaUs; 233385fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 233485fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen } 233585fcbd6aec4eab3368e9266be0a1151a081f204dMarco Nelissen 2336c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 2337c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 2338c059860c73678a202bfa33062723e8f82fb779d9James Dong 2339a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2340a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2341c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 234279761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2343be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2344be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2345be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2346be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2347965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2348be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2349be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2350c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2351be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2352be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 23538644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2354be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2355a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("%s timestampUs/lastTimestampUs: %" PRId64 "/%" PRId64, 235611f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih trackName, timestampUs, lastTimestampUs); 23578644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2358c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 23598644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 236020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2361d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 2362c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 2363d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2364d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 236593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 236693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 236793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 236893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2369faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 237093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 237143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2372c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 237358ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 2374c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2375c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count = (mOwner->use32BitFileOffset() 2376c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 2377c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 2378c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2379c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (count == 0) { 23801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 238158ae9c530247668f8af36e30d228c716c226b3d4James Dong } 238258ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 238358ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 238458ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 238558ae9c530247668f8af36e30d228c716c226b3d4James Dong } 238613aec890216948b0c364f8f92792129d0335f506James Dong 238713aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 238813aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 23891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 23901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 239113aec890216948b0c364f8f92792129d0335f506James Dong } else { 239213aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 239313aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 239413aec890216948b0c364f8f92792129d0335f506James Dong } else { 239543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 239643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 239743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 239843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 239943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 240013aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 240113aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 2402c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 2403c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 2404c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 240513aec890216948b0c364f8f92792129d0335f506James Dong } 24061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 240713aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 240813aec890216948b0c364f8f92792129d0335f506James Dong } 240913aec890216948b0c364f8f92792129d0335f506James Dong } 241013aec890216948b0c364f8f92792129d0335f506James Dong } 241113aec890216948b0c364f8f92792129d0335f506James Dong 241220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 241325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 241445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 2415690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2416f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 241745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2418bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2419be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 242013aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 242143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2422c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(1, mStszTableEntries->count()); 242358ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 24241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 24251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 242613aec890216948b0c364f8f92792129d0335f506James Dong } 242713aec890216948b0c364f8f92792129d0335f506James Dong 2428be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2429be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2430be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2431c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 1) { 24328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 243379761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2434be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2435be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2436be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2437a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2438c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() <= 2) { 243979761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2440a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 244179761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2442a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2443a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 244479761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2445a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2446a472613aec322e25891abf5c77bf3f7e3c244920James Dong 244743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // The last ctts box may not have been written yet, and this 244843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // is to make sure that we write out the last ctts box. 244943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 245043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (cttsSampleCount > 0) { 245143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 245243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 245343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 245443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 2455c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 245625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 245743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 245843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 245943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2460df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 246111f15ddbca475b5f6a3d7970b22234e04c595b37Robert Shih count, nZeroLengthFrames, mStszTableEntries->count(), trackName); 2462872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2463a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs()); 2464872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2465365a963142093a1cd8efdcea76b5f65096a5b115James Dong 246637187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 246737187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 246837187916a486504acaf83bea30147eb5fbf46ae5James Dong } 246937187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2470365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2471365a963142093a1cd8efdcea76b5f65096a5b115James Dong 247245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 2473c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { // no samples written 247429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 247545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 247645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 247745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2478c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (!mIsAudio && mStssTableEntries->count() == 0) { // no sync frames for video 247929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 248045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 248145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 248245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 248345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 248445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 248545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 248645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 248745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 248845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 248945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 249043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 249107ec01904613a0bac32caaa8444b4690998faed7James Dong 249207ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 249307ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 249407ec01904613a0bac32caaa8444b4690998faed7James Dong return; 249507ec01904613a0bac32caaa8444b4690998faed7James Dong } 249607ec01904613a0bac32caaa8444b4690998faed7James Dong 249743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 249843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 249943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 250043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 250143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mIsAudio? 0: 1); 250243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 250343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 250443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 250543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 250643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 250743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 250843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2509c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 251043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 251186b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 251286b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 251386b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 251486b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 251586b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 251686b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 251786b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 251886b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 251986b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 252086b7f47aa7482424cf8fd248f1315311919be3b0James Dong 252186b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 252270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 252370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 252486b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 252570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 252607ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 252707ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 252807ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 252907ec01904613a0bac32caaa8444b4690998faed7James Dong 253043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 253143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 253243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 253343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 253470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 253570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 253670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 253770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 253870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 253970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 254070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 254170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 254243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 254343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 254443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2545faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 2546a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("trackProgressStatus: %" PRId64 " us", timeUs); 2547c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2548215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 2549215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 2550a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs); 2551bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 255293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 255393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 255493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 255593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2556faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 2557bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 2558faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 2559bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 2560faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2561faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 2562faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 2563faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 2564bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2565bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2566faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2567faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 2568faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2569faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2570faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 2571faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 2572bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2573bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2574faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2575faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 2576faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 2577bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2578bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2579faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 2580faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2581faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 2582faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2583d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 2584a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("setDriftTimeUs: %" PRId64 " us", driftTimeUs); 2585e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2586d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 2587e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2588e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2589e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 2590a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("getDriftTimeUs: %" PRId64 " us", mDriftTimeUs); 2591e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2592e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 2593e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2594e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2595de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const { 2596de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui return mIsRealTimeRecording; 2597de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui} 2598de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2599b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 2600b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 2601b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 2602b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 26031c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 26043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 26051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 26061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 26071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 260813aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 260920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 261020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26113b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 2612c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 261320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 261420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2615d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2616d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 2617d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 2618d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2619690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 2620690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 2621690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2622690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2623690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2624690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2625690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2626690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 262729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 2628690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2629690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2630690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2631690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2632690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 263329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 2634690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2635690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2636690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2637690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2638690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2639690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 264120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s track time scale: %d", 26431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 26448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 2645efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 2652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 2654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 2661b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 2666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 2667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 2671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 2676965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong writeCttsBox(); 2677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mIsAudio) { 2678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mp4v"); 2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("s263"); 2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avc1"); 2696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 269729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2698b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 2716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 2717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 2718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 2721c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->writeInt8(0); // compressor string length 2722c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->write(" ", 31); 2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 272643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(23 + mCodecSpecificDataSize, 128); 2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *fourcc = NULL; 2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "samr"; 2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "sawb"; 2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "mp4a"; 2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 275229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 278543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 278843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(mCodecSpecificDataSize + 23, 128); 2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // max bit rate 2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // avg bit rate 2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 2821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 282243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 0x77, 0x00, 2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00, 2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00 2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2853b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2859efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 2860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 2861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 2862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 2863b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 2864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2866219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 28688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 2869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 2870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 2871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 2876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 2877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 288120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 2888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 2895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 2901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 2902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 2909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 2916b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 2924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2928efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 2929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 2930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 2931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 2935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 2936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 2937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 2938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 2939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 2940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 2942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // language code 2943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 2948b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 2955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 2960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 2961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 2962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 2964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 2967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 2968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 2970b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 2971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 2972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 2976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 2977b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 2978b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2979b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 298243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mCodecSpecificDataSize, 5); 2983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2984b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 2985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 2986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 2987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 2988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 2989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2990b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 2991b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2992b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2993b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 2994b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 2995b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 2996b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2997b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 2998b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 2999b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 3000b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3001b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3002b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 3003b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 3004b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 3006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 3008b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 3010000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 3011a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 3012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 3013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 301443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 3015b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 3016b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3017000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 3018000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 3019000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3020000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 3021000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 3022000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3023c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3024c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mSttsTableEntries->get(duration, 1)); 3025c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back to host byte order 3026c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 3027c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 3028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 3029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 303020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3031965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 3032965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { // ctts is not for audio 3033965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3034965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3035965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3036000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 3037000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 3038000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 3039000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 3040000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 3041965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 3042c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 3043965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 3044965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 3045965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3046a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]", 3047c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 3048965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3049965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 3050000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 3051c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 3052c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCttsTableEntries->get(duration, 1)); 3053c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back host byte order 3054c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1); 3055c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 3056965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 3057965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 3058965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3059b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 3060b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 3061b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3062c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 3063b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 3064b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 306525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 3066b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 3067b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 3068b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3069c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 3070c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 3071b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 3072b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 307320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3074b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 3075b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 3076b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3077c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 3078b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 3079b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 308020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3081b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 3082b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 3083b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3084c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 3085c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 3086c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 3087c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 3088b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3089b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 309020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 309120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 309207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 309307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 309407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 309507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 309607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 309707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 309807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 309907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 310007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 310107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 310207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 310307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 310407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 310507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 310607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 3107432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 3108432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 310907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 311007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 311107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 311207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 311307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 311407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 311507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 311607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 311720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3118