MPEG4Writer.cpp revision 1f1f2b1678fd0d038dfc501252dd2b65ecf10cae
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#include <utils/Log.h> 20050b28a593350047845a45a14cc5026221ac1620James Dong 2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h> 2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h> 24a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/prctl.h> 2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong#include <media/stagefright/foundation/ADebug.h> 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 3018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 3103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h> 3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 34d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h> 3507ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.h> 36674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <sys/types.h> 37674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <sys/stat.h> 38674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <fcntl.h> 39674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <unistd.h> 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h" 4219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4577e8ae9967a078770416619e99ddb5b010def312James Dongstatic const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024; 461f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachadstatic const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32 471f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad // filesystem file size 481f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad // used by most SD cards 493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07; 503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08; 5170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs = 700000LL; 525b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 55bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId); 568f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 6037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t stop(); 6137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 6225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 643b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 65d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 66b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTrackHeader(bool use32BitOffset = true); 671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 71c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong void addChunkOffset(off64_t offset); 7270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int32_t getTrackId() const { return mTrackId; } 73dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 76000e18370baae60ffd9f25b509501dd8c26deabfJames Dong enum { 77000e18370baae60ffd9f25b509501dd8c26deabfJames Dong kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 788c460498c028888c533ab442be12b6d4b669b965James Dong kSampleArraySize = 1000, 79000e18370baae60ffd9f25b509501dd8c26deabfJames Dong }; 80000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 81c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // A helper class to handle faster write box with table entries 82c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong template<class TYPE> 83c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong struct ListTableEntries { 84c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity) 85c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mElementCapacity(elementCapacity), 86c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEntryCapacity(entryCapacity), 87c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTotalNumTableEntries(0), 88c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry(0), 89c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement(NULL) { 90c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mElementCapacity, 0); 91c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mEntryCapacity, 0); 92c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 93c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 94c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Free the allocated memory. 95c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ~ListTableEntries() { 96c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (!mTableEntryList.empty()) { 97c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 98c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete[] (*it); 99c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.erase(it); 100c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 101c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 102c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 103c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Replace the value at the given position by the given value. 104c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // There must be an existing value at the given position. 105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order 106c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 107c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void set(const TYPE& value, uint32_t pos) { 10825f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity); 109c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 110c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 111c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 112c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 114c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 115c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 116c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 117c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value; 120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Get the value at the given position by the given value. 123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value the retrieved value at the position in network byte order. 124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 125c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @return true if a value is found. 126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool get(TYPE& value, uint32_t pos) const { 12725f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong if (pos >= mTotalNumTableEntries * mEntryCapacity) { 128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return false; 129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong value = (*it)[(pos % (mElementCapacity * mEntryCapacity))]; 141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return true; 142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Store a single value. 145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order. 146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void add(const TYPE& value) { 147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nValues = mNumValuesInCurrEntry % mEntryCapacity; 150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries == 0 && nValues == 0) { 151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity]; 152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCurrTableEntriesElement != NULL); 153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.push_back(mCurrTableEntriesElement); 154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t pos = nEntries * mEntryCapacity + nValues; 157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement[pos] = value; 158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mNumValuesInCurrEntry; 160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) { 161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mTotalNumTableEntries; 162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry = 0; 163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Write out the table entries: 167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 1. the number of entries goes first 168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 2. followed by the values in the table enties in order 169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg writer the writer to actual write to the storage 170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void write(MPEG4Writer *writer) const { 171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0); 172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries; 173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->writeInt32(nEntries); 174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong it != mTableEntryList.end(); ++it) { 176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(nEntries, 0); 177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries >= mElementCapacity) { 178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity); 179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong nEntries -= mElementCapacity; 180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries); 182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong break; 183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Return the number of entries in the table. 188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count() const { return mTotalNumTableEntries; } 189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong private: 191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mElementCapacity; // # entries in an element 192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mEntryCapacity; // # of values in each entry 193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mTotalNumTableEntries; 194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mNumValuesInCurrEntry; // up to mEntryCapacity 195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong TYPE *mCurrTableEntriesElement; 196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mutable List<TYPE *> mTableEntryList; 197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong }; 200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 201c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 202c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 205693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 207a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 208a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 209eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 2101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 2111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 2121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 213bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 214c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 21543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 216e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 217d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 2181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 2198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 223be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 22413aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 2251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool mSamplesHaveSameSize; 227c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStszTableEntries; 228be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStcoTableEntries; 230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<off64_t> *mCo64TableEntries; 231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStscTableEntries; 232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStssTableEntries; 233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mSttsTableEntries; 234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mCttsTableEntries; 235965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 236000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMinCttsOffsetTimeUs; 237000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMaxCttsOffsetTimeUs; 238965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 2403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 2413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 2423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 2433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 2443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 2453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 2463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 2473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 2483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 2493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 2503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 2513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 2523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 255548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 25693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 25825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 2593c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 26070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 26170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 26293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 26393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 26425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 265872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 266872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 267872a481558350634a3fd5cb67939de288af00ecbJames Dong 268000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int32_t getStartTimeOffsetScaledTime() const; 269000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 27137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 2743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 2753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 276b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 278b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 279215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 280215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 281faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 28293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 28303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 28419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 28519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 286c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 287c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 288c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 289c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 290c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 291c059860c73678a202bfa33062723e8f82fb779d9James Dong 292690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 293690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 29413f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t mRotation; 295690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 2971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 2981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 29979761ab096f57c3027fad9556c2bc436672d614eJames Dong 30079761ab096f57c3027fad9556c2bc436672d614eJames Dong // Duration is time scale based 30179761ab096f57c3027fad9556c2bc436672d614eJames Dong void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 302965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 30345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 30445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong bool isTrackMalFormed() const; 30543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 3061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 307b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 309b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 310b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 311b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 312b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 313965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void writeCttsBox(); 314b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 318b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 319b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 321efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeMdhdBox(uint32_t now); 322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 324b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 325efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeTkhdBox(uint32_t now); 326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 337674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(-1), 338674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(NO_INIT), 339de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording(true), 340b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 3411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 342a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 343a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 344a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 345411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 34620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 34713aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 3487837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 34907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 35007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 35107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 35286b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 35386b7f47aa7482424cf8fd248f1315311919be3b0James Dong mStartTimeOffsetMs(-1) { 354674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong 355af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); 356674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mFd >= 0) { 357674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck = OK; 358674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong } 35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36130ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 362674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(dup(fd)), 363674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(mFd < 0? NO_INIT: OK), 364de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording(true), 365b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 3661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 367a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 368a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 369a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 370411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 37130ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 37213aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 3737837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 37407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 37507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 37607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 37786b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 37886b7f47aa7482424cf8fd248f1315311919be3b0James Dong mStartTimeOffsetMs(-1) { 37930ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 38030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 38120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 3828bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong reset(); 38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 3851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 3871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 3881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 393dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 394dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 395dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 396dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 397dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 398dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 399dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 400dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 401dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 402dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 403dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 404dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 405dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 406dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 407dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 408dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 409dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 410dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 411dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) const { 412dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 413dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 414dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 415dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 416dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 417dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 418dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 419dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 420c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 42113210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 42213210f3346462a86ce9fe3af72a0c200dba84e27James Dong snprintf(buffer, SIZE, " duration encoded : %lld us\n", mTrackDurationUs); 42313210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 424dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 425dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 426dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 427dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 4282dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 429bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 430bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 43129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Attempt to add source AFTER recording is started"); 432bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 433bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 434acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 435acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // At most 2 tracks can be supported. 436acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.size() >= 2) { 437acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("Too many tracks (%d) to add", mTracks.size()); 438acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 439acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 440acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 441acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong CHECK(source.get() != NULL); 442acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 443acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // A track of type other than video or audio is not supported. 444acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong const char *mime; 445acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong source->getFormat()->findCString(kKeyMIMEType, &mime); 446acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong bool isAudio = !strncasecmp(mime, "audio/", 6); 447acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong bool isVideo = !strncasecmp(mime, "video/", 6); 448acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (!isAudio && !isVideo) { 449acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("Track (%s) other than video or audio is not supported", 450acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong mime); 451acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 452acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 453acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 454acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // At this point, we know the track to be added is either 455acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // video or audio. Thus, we only need to check whether it 456acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // is an audio track or not (if it is not, then it must be 457acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // a video track). 458acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 459acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // No more than one video or one audio track is supported. 460acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong for (List<Track*>::iterator it = mTracks.begin(); 461acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong it != mTracks.end(); ++it) { 462acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if ((*it)->isAudio() == isAudio) { 463acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("%s track already exists", isAudio? "Audio": "Video"); 464acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return ERROR_UNSUPPORTED; 465acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 466acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 467acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 468acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // This is the first track of either audio or video. 469acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong // Go ahead to add the track. 470219f195159f93d627af2b243732e3f9020511a46James Dong Track *track = new Track(this, source, 1 + mTracks.size()); 47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 4722dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 4732dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 47693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 477acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong if (mTracks.empty()) { 478acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong ALOGE("No source added"); 479acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong return INVALID_OPERATION; 480acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong } 481acc47642e0f5d962f6289e6ba687fabf68f8312bJames Dong 482a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 483a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 48493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 485a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 486a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 487a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 488a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 489a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 490a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 491a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 492a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 493a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 494a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 495a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 496a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 497a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 4982dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 4992dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 5002dec2b5be2056c6d9428897dc672185872d30d17James Dong // 5012dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 5022dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 5032dec2b5be2056c6d9428897dc672185872d30d17James Dong 50478a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 5052dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 50678a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 5072dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 5082dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 5092dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 5102dec2b5be2056c6d9428897dc672185872d30d17James Dong 5112dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 5122dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 5132dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 51478a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 5152dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 5162dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 5172dec2b5be2056c6d9428897dc672185872d30d17James Dong 51878a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 519a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 52078a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 52178a1a286f736888ae7af8860b2c424af0d978848James Dong } 52278a1a286f736888ae7af8860b2c424af0d978848James Dong 52378a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 52478a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 52578a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 52678a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 52778a1a286f736888ae7af8860b2c424af0d978848James Dong ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000); 52878a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 52978a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 53078a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 53178a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 53278a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 53378a1a286f736888ae7af8860b2c424af0d978848James Dong } 53478a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 53578a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 53678a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 53778a1a286f736888ae7af8860b2c424af0d978848James Dong } 5382dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5392dec2b5be2056c6d9428897dc672185872d30d17James Dong } 54078a1a286f736888ae7af8860b2c424af0d978848James Dong 5412dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 5422dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 5432dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5442dec2b5be2056c6d9428897dc672185872d30d17James Dong 5452dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 5462dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 5472dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 5482dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 5492dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5502dec2b5be2056c6d9428897dc672185872d30d17James Dong 551df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 5522dec2b5be2056c6d9428897dc672185872d30d17James Dong " moov size %lld bytes", 5532dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 5542dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 5552dec2b5be2056c6d9428897dc672185872d30d17James Dong} 5562dec2b5be2056c6d9428897dc672185872d30d17James Dong 5572dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 558674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 55925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 562a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 563a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 564a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 565a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 566a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 567a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 568a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 569a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 570a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 571a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 5722dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 5732dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 5742dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 5752dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 5762dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 5772dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5782dec2b5be2056c6d9428897dc672185872d30d17James Dong 5791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 5801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 5811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 5821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 5831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 5841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 5851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 5861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 5871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 5885ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("32-bit file size limit (%lld bytes) too big. " 589d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong "It is changed to %lld bytes", 590d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 591d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 5921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 5931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 5941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 595b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 596b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 597b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 598b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 599b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 6002dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6012dec2b5be2056c6d9428897dc672185872d30d17James Dong 602de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui int32_t isRealTimeRecording; 603de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) { 604de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mIsRealTimeRecording = isRealTimeRecording; 605de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 606de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 607065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 60893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 609a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 610a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 611a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 61293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 613a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 614a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 615a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 616a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 6178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 6188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 6198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 6208f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 62143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 6223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("movie time scale: %d", mTimeScale); 6238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 62477e8ae9967a078770416619e99ddb5b010def312James Dong /* 62577e8ae9967a078770416619e99ddb5b010def312James Dong * When the requested file size limit is small, the priority 62677e8ae9967a078770416619e99ddb5b010def312James Dong * is to meet the file size limit requirement, rather than 6277b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to make the file streamable. mStreamableFile does not tell 6287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * whether the actual recorded file is streamable or not. 62977e8ae9967a078770416619e99ddb5b010def312James Dong */ 63077e8ae9967a078770416619e99ddb5b010def312James Dong mStreamableFile = 63177e8ae9967a078770416619e99ddb5b010def312James Dong (mMaxFileSizeLimitBytes != 0 && 63277e8ae9967a078770416619e99ddb5b010def312James Dong mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 63377e8ae9967a078770416619e99ddb5b010def312James Dong 6347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong /* 6357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory is true if the amount of data in moov box is 6367b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * smaller than the reserved free space at the beginning of a file, AND 6377b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * when the content of moov box is constructed. Note that video/audio 6387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * frame data is always written to the file but not in the memory. 6397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Before stop()/reset() is called, mWriteMoovBoxToMemory is always 6417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * false. When reset() is called at the end of a recording session, 6427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Moov box needs to be constructed. 6437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory 6457b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to set to mStreamableFile so that if 6467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the file is intended to be streamable, it is set to true; 6477b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * otherwise, it is set to false. When the value is set to false, 6487b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * all the content of the moov box is written immediately to 6497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the end of the file. When the value is set to true, all the 6507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * content of the moov box is written to an in-memory cache, 6517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mMoovBoxBuffer, util the following condition happens. Note 6527b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * that the size of the in-memory cache is the same as the 6537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * reserved free space at the beginning of the file. 6547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 2) While the data of the moov box is written to an in-memory 6567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache, the data size is checked against the reserved space. 6577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * If the data size surpasses the reserved space, subsequent moov 6587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * data could no longer be hold in the in-memory cache. This also 6597b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * indicates that the reserved space was too small. At this point, 6607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * _all_ moov data must be written to the end of the file. 6617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory must be set to false to direct the write 6627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to the file. 6637b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 3) If the data size in moov box is smaller than the reserved 6657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space after moov box is completely constructed, the in-memory 6667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache copy of the moov box is written to the reserved free 6677b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space. Thus, immediately after the moov is completedly 6687b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * constructed, mWriteMoovBoxToMemory is always set to false. 6697b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong */ 6707b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 6717837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 6727837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 6737837c17063a4c50bc856ba59418516fdab731de7James Dong 674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6767837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6787837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 6792dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 6802dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 6812dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 6822dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6832dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 6847837c17063a4c50bc856ba59418516fdab731de7James Dong } 68543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mEstimatedMoovBoxSize, 8); 68677e8ae9967a078770416619e99ddb5b010def312James Dong if (mStreamableFile) { 68777e8ae9967a078770416619e99ddb5b010def312James Dong // Reserve a 'free' box only for streamable file 68877e8ae9967a078770416619e99ddb5b010def312James Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 68977e8ae9967a078770416619e99ddb5b010def312James Dong writeInt32(mEstimatedMoovBoxSize); 69077e8ae9967a078770416619e99ddb5b010def312James Dong write("free", 4); 69177e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 69277e8ae9967a078770416619e99ddb5b010def312James Dong } else { 69377e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mOffset; 69477e8ae9967a078770416619e99ddb5b010def312James Dong } 6957837c17063a4c50bc856ba59418516fdab731de7James Dong 6967837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 697c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 6981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 6991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 7001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 7011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 7021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 7031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 7051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 7061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 7071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 7081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 710a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 711a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 7131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 714a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 71525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 7191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 7201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 7211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 72237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 723674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 72437187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 725a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 726a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 72737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 728a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 729a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 73037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 73137187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 73237187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 73337187916a486504acaf83bea30147eb5fbf46ae5James Dong } 734a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 73537187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 736a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 737a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 7381c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 739b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping writer thread"); 740411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 741411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 742411ba422e3635d534928ffd81abf54f4f291c739James Dong } 7431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 7451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 7461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 7481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 7491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 7501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 7521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 753411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 754b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Writer thread stopped"); 7551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 7561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 75713f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 75813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 75913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 76013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 76113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 76213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 76313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 76413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 76513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 76613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 76713f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 76813f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 7693856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeCompositionMatrix"); 77013f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 77113f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 77213f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 77313f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 77413f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 77513f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 77613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 77713f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 77813f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 77913f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 78013f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 78113f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 78213f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 78313f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 78413f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 78513f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 78613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 78713f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 78813f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 78913f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 79013f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 79113f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 79213f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 79313f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 79413f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 79513f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 79613f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 79713f6284305e4b27395a23db7882d670bdb1bcae1James Dong 79813f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 79913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 80013f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 80113f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 80213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 80313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 80413f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 80513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 80613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 80713f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 80813f6284305e4b27395a23db7882d670bdb1bcae1James Dong 809411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 810411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 811411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 812411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 813411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 814411ba422e3635d534928ffd81abf54f4f291c739James Dong} 81513f6284305e4b27395a23db7882d670bdb1bcae1James Dong 8168bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() { 817674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 81837187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 819411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 820411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 821411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 822411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 823411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 824411ba422e3635d534928ffd81abf54f4f291c739James Dong } 825411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 826411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 827411ba422e3635d534928ffd81abf54f4f291c739James Dong } 82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 83037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 8318f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 83265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 83320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 83420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 83537187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 83637187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 83737187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 83837187916a486504acaf83bea30147eb5fbf46ae5James Dong } 83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 8418f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 8428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 84320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 84465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 84565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 84665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 84765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 84865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 84965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 850b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Duration from tracks range is [%lld, %lld] us", 85165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 8557837c17063a4c50bc856ba59418516fdab731de7James Dong 85637187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 85737187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 858411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 85937187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 86037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 86137187916a486504acaf83bea30147eb5fbf46ae5James Dong 86220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 8631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 864c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 8651f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); 866c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 8671acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 868c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 8691f1f2b1678fd0d038dfc501252dd2b65ecf10caeRachad uint64_t size = mOffset - mMdatOffset; 8701acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 871c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 8721acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 873c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 87420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8757b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Construct moov box now 8767837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 8777b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = mStreamableFile; 8787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 8797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // There is no need to allocate in-memory cache 8807b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // for moov box if the file is not streamable. 8817b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 8827b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 8837b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong CHECK(mMoovBoxBuffer != NULL); 8847b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 88620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // mWriteMoovBoxToMemory could be set to false in 8887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // MPEG4Writer::write() method 8897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 8907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 8917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Content of the moov box is saved in the cache, and the in-memory 8927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // moov box needs to be written to the file in a single shot. 8937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 89443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 8957837c17063a4c50bc856ba59418516fdab731de7James Dong 8967837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 897c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 8987837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 899674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 9007837c17063a4c50bc856ba59418516fdab731de7James Dong 9017837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 902c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 9037837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 9047837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 9057b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } else { 9067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ALOGI("The mp4 file will not be streamable."); 9077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 9087837c17063a4c50bc856ba59418516fdab731de7James Dong 9097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Free in-memory cache for moov box 9107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mMoovBoxBuffer != NULL) { 9117837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 9127837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 9137837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 9147837c17063a4c50bc856ba59418516fdab731de7James Dong } 9157837c17063a4c50bc856ba59418516fdab731de7James Dong 9160c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 91720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 918411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 91937187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 92120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 922efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() { 923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 924efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 925efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // while time function returns Unix epoch values which starts 926efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // at 1970-01-01. Lets add the number of seconds between them 927efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60); 928efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson return mpeg4Time; 929efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson} 930efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson 931efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 932efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 948b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 95907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 96007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 96107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 963b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 966b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 9702cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 973b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 9778284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 9788284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("isom"); 9798284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("3gp4"); 980b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 9818284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 9828284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeInt32(0); 983b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 9848284de3be2ac07d8774b15e6565df5aba084db04Robert Shih writeFourcc("mp42"); 985b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 986b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 987b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 988b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 989b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 99007ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 99107ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 99207ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 99307ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 99407ec01904613a0bac32caaa8444b4690998faed7James Dong 99507ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 99607ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 99707ec01904613a0bac32caaa8444b4690998faed7James Dong char value[PROPERTY_VALUE_MAX]; 99807ec01904613a0bac32caaa8444b4690998faed7James Dong if (property_get("rw.media.record.test", value, NULL) && 99907ec01904613a0bac32caaa8444b4690998faed7James Dong (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 100007ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 100107ec01904613a0bac32caaa8444b4690998faed7James Dong } 100207ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 100307ec01904613a0bac32caaa8444b4690998faed7James Dong} 100407ec01904613a0bac32caaa8444b4690998faed7James Dong 100570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 100607ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 100707ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 100807ec01904613a0bac32caaa8444b4690998faed7James Dong return; 100907ec01904613a0bac32caaa8444b4690998faed7James Dong } 101007ec01904613a0bac32caaa8444b4690998faed7James Dong 101170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 101270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 101370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 101470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 101570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 101670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 101770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 101870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 101970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 102013aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 102113aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 102213aec890216948b0c364f8f92792129d0335f506James Dong return OK; 102313aec890216948b0c364f8f92792129d0335f506James Dong} 102413aec890216948b0c364f8f92792129d0335f506James Dong 102513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 102613aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 102713aec890216948b0c364f8f92792129d0335f506James Dong} 102813aec890216948b0c364f8f92792129d0335f506James Dong 102913aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 103013aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 103113aec890216948b0c364f8f92792129d0335f506James Dong} 103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1033c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 1034c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 103520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1036c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1037c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1038c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 103920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 104020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 104120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 104220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 104320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 104420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 104503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 104603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 104703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 104803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 104903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 105003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 105103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 105203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 105303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 105403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 105503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 105603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 105703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 105803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1059c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 1060c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 106130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 106230ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 106303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1064b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 1065b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 1066c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1067b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 1068c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1069b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 1070c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1071b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1072c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1073c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 1074c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1075c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1076c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 1077b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1078b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 1079b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 108043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(length, 65536); 108130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1082b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 1083c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1084b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1085c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1086c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1087b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 1088b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 108930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 109030ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 109130ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 109230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 10937837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 1094674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 10957837c17063a4c50bc856ba59418516fdab731de7James Dong 10967837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 10977837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 10987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 1099c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 11001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 11017b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // The reserved moov box at the beginning of the file 11027b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // is not big enough. Moov box should be written to 11037b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the end of the file from now on, but not to the 11047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // in-memory cache. 11057b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 11067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // We write partial moov box that is in the memory to 11077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the file first. 1108c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 11097837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 11107837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 11117837c17063a4c50bc856ba59418516fdab731de7James Dong } 1112674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 1113674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 11147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ::write(mFd, ptr, bytes); 11157837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 11167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 11177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // All subsequent moov box content will be written 11187b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // to the end of the file. 11197837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 11207837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 11217837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 11227837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 11237837c17063a4c50bc856ba59418516fdab731de7James Dong } 11247837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1125674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 11267837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 11277837c17063a4c50bc856ba59418516fdab731de7James Dong } 11287837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 11297837c17063a4c50bc856ba59418516fdab731de7James Dong} 11307837c17063a4c50bc856ba59418516fdab731de7James Dong 113120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 11320c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11347837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 11357837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 113620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 113720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 113820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 113920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 114020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 114120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 11420c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1144c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 114520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 114620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11477837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 11487837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 11497837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 11507837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1151c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 11527837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 11537837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1154c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 11557837c17063a4c50bc856ba59418516fdab731de7James Dong } 115620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 115720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1159674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 116020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 116220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 116320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1164674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 116620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1169674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1174674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1179674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 11830c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 1184674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 118807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 118907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 119007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 119107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 119207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 119307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 119407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 119507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 119607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 119707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 119807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 119907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 120007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 120107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 120207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 120307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 120407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 120507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 120607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 120707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 120807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 120907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 121007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 121107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 121207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 121307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 121407b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 121507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 121607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 121707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 121807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 121907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 122007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 122107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 122207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 122307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 122407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 122507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 122607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 122707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 122807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 122907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 123007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 123107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 123207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 123307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 123407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 123507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 123607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 123707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 123807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 123907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 124007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 124107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 124207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 124307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 124407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 124507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 124607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 124707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 124807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 124907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 125007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 125107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 125207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 125307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 125407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 125507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 125607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 125707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1259674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 126278a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 126378a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 126478a1a286f736888ae7af8860b2c424af0d978848James Dong} 126578a1a286f736888ae7af8860b2c424af0d978848James Dong 1266d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1267d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1268d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1269d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1270d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1271d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1272956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1273d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1274d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1275d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1276d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 12771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 127877e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 127977e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 128077e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 128177e8ae9967a078770416619e99ddb5b010def312James Dong } 1282acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1283acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1284acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1285acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1286d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1287d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1288d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1289d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1290d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1291d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1292d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1293d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1294d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1295d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1296d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1297d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1298d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1299d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1300d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1301d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1302d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 130325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 130425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 130525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 130625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 130725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 130825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 130925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 131025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 131125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 131225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 131325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 131425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 131525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1316f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1317df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("setStartTimestampUs: %lld", timeUs); 131843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 13193c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1320065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1321f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1322df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Earliest track starting time: %lld", mStartTimestampUs); 13233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 13243c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 13253c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1326f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 13273c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 13283c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 13293c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 13303c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 133158ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 133258ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 133358ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 133458ae9c530247668f8af36e30d228c716c226b3d4James Dong} 133558ae9c530247668f8af36e30d228c716c226b3d4James Dong 133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1339bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 134125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1344a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1345a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1346eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1347bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1348c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1349956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1350be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1351c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1352c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1353c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)), 1354c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)), 1355c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1356c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 1357c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 135925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1360548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 136113f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 136213f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 136319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 13648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 13651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 13661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 13671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 13681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 13691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 13701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 13711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1372c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1373c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1374c059860c73678a202bfa33062723e8f82fb779d9James Dong 13751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 13761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1377c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1378c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 1379c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 1380c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1381c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 13821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 138378a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 138478a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 138578a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 138678a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1387c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1388c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1389c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1390c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 139178a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 139278a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 139378a1a286f736888ae7af8860b2c424af0d978848James Dong } 13941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 13951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 13961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 13971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 13981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1399c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(chunkId)); 1400c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(sampleId)); 1401c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(1)); 14021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1405c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 14061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 140979761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 14101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 14115a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 14125ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("0-duration samples found: %d", sampleCount); 14135a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1414c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1415c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 14161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1418965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1419965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1420965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1421965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { 1422965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1423965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1424c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1425c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1426965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1427965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1428c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1429c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1430c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1431c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1432c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1433c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1434c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 14351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 14361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1437c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 14383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 1439c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1440c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1441c059860c73678a202bfa33062723e8f82fb779d9James Dong 1442c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1443c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1444c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1445c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1446c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1447c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1448c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1449c059860c73678a202bfa33062723e8f82fb779d9James Dong 1450c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1451c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1452c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1453c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1454c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1455c059860c73678a202bfa33062723e8f82fb779d9James Dong 145643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 145719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 145819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 145919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 146019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 146119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 146219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 146319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 146419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 146519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 146619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 146719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 146819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 146919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 147019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 147119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 147219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 147319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 147419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 147519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 147619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 147719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 147819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 147919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 148019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 148119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 148219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 148319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 148419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 148519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 148619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 148719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 148820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 149020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1493c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 1494c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 1495c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 1496c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 1497c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 1498c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 1499c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 1500c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 1501c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 1502c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 1503c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 1504c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 1505c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 1506c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 1507c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 1508c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 150920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 151020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 151120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 151220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 151320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 151420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 151593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 15163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 151793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 151893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 151993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 152093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 152193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 152293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 15233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Receive request to track progress status for every %lld us", timeUs); 152493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 152593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 152693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 152793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 152893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 152993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 15301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 15311c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 15323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 15331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 15341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 15351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 15361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15381c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 15393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 15401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 15411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 15421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 15441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 15451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 15471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 15481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 15491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 15501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 155343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 15541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1556fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 15573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeChunkToFile: %lld from %s track", 15585410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video"); 1559fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1560fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1561fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1562fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1563fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1564fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong off64_t offset = chunk->mTrack->isAvc() 1565fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong ? addLengthPrefixedSample_l(*it) 1566fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1567fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1568fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1569fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1570fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 15711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 15741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1575fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 15761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1577fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 15781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1580fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 15813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 15821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 158370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 158470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1585e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 158670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 15871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 158870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 158970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 159070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 15911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 1592b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%d chunks are written in the last batch", outstandingChunks); 15931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1595fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 15963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 15971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 15991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 16001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 16011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 16021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 16031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 16041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 16051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 16061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 16071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 16123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 1613fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 16141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 16171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 16181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1619fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 16201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 16211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 16221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1623fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1624fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1625fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 162670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 162770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 162870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 162970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 163070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 163170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 163270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1633fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 16341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1636fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1637fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 16381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16401c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 16413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 16421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1643a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1644fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1645fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 16461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1647fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1648fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1649fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1650fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 16511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 16521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1654de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // In real time recording mode, write without holding the lock in order 1655de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // to reduce the blocking time for media track threads. 1656de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // Otherwise, hold the lock until the existing chunks get written to the 1657de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui // file. 1658fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 1659de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1660de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.unlock(); 1661de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1662fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 1663de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mIsRealTimeRecording) { 1664de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui mLock.lock(); 1665de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 1666fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 16671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1668fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1669fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 16701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16721c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 16733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 16741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 16761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1677e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 16781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 16791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 16801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 16811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 168270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 168370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 16841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 16851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 16881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 16891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 16901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 16911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 1692411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 16931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 16941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 169793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1698a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1699a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1700a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1701a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1702a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 170325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 170493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 170519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 170619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 170719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 170870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 170919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 171013f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 171113f6284305e4b27395a23db7882d670bdb1bcae1James Dong if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 171213f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 171313f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 171413f6284305e4b27395a23db7882d670bdb1bcae1James Dong 171593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 171693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1717f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1718de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) { 1719a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 1720a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 1721a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 1722a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 1723a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 1724a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 172586b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 172686b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 1727a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 172886b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 172986b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 173086b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 173186b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 173286b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 1733df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Start time offset: %lld us", startTimeOffsetUs); 1734a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 1735a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1736f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1737a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1738f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 173925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 174025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 174125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 174225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 174320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 174420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 174520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 174620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 174720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 174820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1749eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 1750c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 175125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1752956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 17531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 175443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 175520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 175625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 175720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 175825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 175925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 176020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 176120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 176237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1763a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 176437187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1765a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1766a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 176737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 176872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track stopping", mIsAudio? "Audio": "Video"); 1769eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 177029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 1771eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 1772eaae38445a340c4857c1c5569475879a728e63b7James Dong } 1773eaae38445a340c4857c1c5569475879a728e63b7James Dong 177420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 177537187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 177620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 177720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 177820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 177972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track source stopping", mIsAudio? "Audio": "Video"); 178072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang mSource->stop(); 178172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang ALOGD("%s track source stopped", mIsAudio? "Audio": "Video"); 178272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang 178320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 178420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 178537187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = (status_t) dummy; 178637187916a486504acaf83bea30147eb5fbf46ae5James Dong 1787b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%s track stopped", mIsAudio? "Audio": "Video"); 178837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 178920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 179020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 179125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 179225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 179325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 179425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 179520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 179620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 179720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 179820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 179937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 180037187916a486504acaf83bea30147eb5fbf46ae5James Dong return (void *) err; 180120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 180220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 18043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 18053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 18073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 18083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 18113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 18123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18133856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findNextStartCode: %p %d", data, length); 18143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 18163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 18173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 18183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 18193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 18213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 18223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 18243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 18273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 18283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 18303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 18313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 18323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 18343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 18353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 183629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 18373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 18383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 18413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 18423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 184329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 18443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 18453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 18473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 18483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 18493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 18503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 18513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 18523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 18533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 185429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 18553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 18563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 18593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 18603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 18613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 18633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 18663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 18673856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 18683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 18703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 18713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 187229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Codec specific data length too short: %d", size); 18733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 18773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 18783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 18793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 18803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 18833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 18843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 18863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 18873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 18883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 18893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 18903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 18913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 18923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 18933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 18943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 18953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 18963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 18973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 18983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 18993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 19003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 190129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 19023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 19063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 19083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 19093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 191029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 19113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 191829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 19233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 19293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 19303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 193629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 19373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 194129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 19423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 19473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 19483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 19493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 195029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 19513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 195429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Too many pic parameter sets (%d) found", nPicParamSets); 19553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19581374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 19591374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 19601374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 19611374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 19623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 19633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 19643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 19653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 19663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 196729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 19683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 19693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19711374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 19723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 19733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 1974548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 197503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 197603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 1977548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 197803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 197929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 198003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 198103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 198203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 198429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Codec specific data length too short: %d", size); 198503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 198603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 198703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 19893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 19903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 199103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 199203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 199403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 199503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 199603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 19983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 199903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 200003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 20013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 20023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 20033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 20043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 200503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 2007b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2008b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 2009b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2010b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 2011b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 201203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 20143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 20153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 20163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 20173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 20183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 20193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 20203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 20213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 20223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 20233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 20253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 20263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 20273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 20283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 20303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 20313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 20323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 20333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 20343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 20353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 20363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 20373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 20383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 20393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 20403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 20413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 20423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 20433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 204403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 204503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 204603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 204703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 2048872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 2049872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 2050872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 2051872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 2052872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 2053872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2054872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 2055872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 2056872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2057872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 2058872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2059872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2060872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2061872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 2062872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2063872a481558350634a3fd5cb67939de288af00ecbJames Dong} 2064872a481558350634a3fd5cb67939de288af00ecbJames Dong 206537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 206630ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 206713aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 206843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 206913aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 207013aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 207113aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 2072965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 2073965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 2074965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 2075965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 2076965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 2077000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 2078a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 2079965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 2080000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 2081000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2082000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 208343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2084c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 2085e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2086a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 2087a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 2088a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } else { 2089a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 2090a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 2091de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2092de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2093de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2094de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui } 2095985f838934510983d8a887461e98dca60a6e858fJames Dong 2096d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 209720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 209893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 209920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 210093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 210120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 210220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 210320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 210413aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 210520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 210620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 210720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2108a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 2109a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 2110a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2111a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2112a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2113a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2114a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2115a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2116a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 211730ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 211830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 211903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 212003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 212103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 2122548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 2123548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 21241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 212503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 212603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 212703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 212803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 212943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_EQ((status_t)OK, err); 21301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 213103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 213203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 213303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 213403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 213503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 213603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 213730ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 213830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 213930ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 214030ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 214130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2142548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 214330ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2144a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2145a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2146d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2147d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2148d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2149d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2150d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2151d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2152d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2153d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2154d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2155d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 21561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 2157e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2158b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 2159b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mIsAvc) { 2160b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2161b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2162b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2163b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2164b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2165b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2166050b28a593350047845a45a14cc5026221ac1620James Dong 2167d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 21681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 21691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 21701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2171d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2172d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2173d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2174d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2175d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2176d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2177d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2178d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2179d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2180050b28a593350047845a45a14cc5026221ac1620James Dong 2181d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2182d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2183d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2184d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2185d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 218770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2188f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2189f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 21908428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 21913c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 219248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2193a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 21948428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 219543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(durExcludingEarlierPausesUs, 0ll); 21968428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 219743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(pausedDurationUs, lastDurationUs); 21988428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2199a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2200a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2201a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2202a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 220343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timestampUs, 0ll); 2204000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (!mIsAudio) { 2205965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2206965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2207965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2208000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 2209965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 2210965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 2211965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2212965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 2213000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 2214000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 221543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(cttsOffsetTimeUs, 0ll); 2216965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 2217000e18370baae60ffd9f25b509501dd8c26deabfJames Dong ALOGV("decoding time: %lld and ctts offset time: %lld", 2218000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 2219000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2220000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 2221000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 2222000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 222343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL); 2224c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 222543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 222643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 222743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 222843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 222943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 223043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 223143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 223243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 223343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 223443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 223543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 223643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 223743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 223843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 223943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 2240000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2241000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 2242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 2243000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2244000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2245000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 2246000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2247000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2248000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2249000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2250000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2251000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2252000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2253965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2254872a481558350634a3fd5cb67939de288af00ecbJames Dong 2255de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui if (mOwner->isRealTimeRecording()) { 2256872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2257872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 2258e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2259e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2260872a481558350634a3fd5cb67939de288af00ecbJames Dong 226143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timestampUs, 0ll); 22623856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s media time stamp: %lld and previous paused duration %lld", 22638428af5381e835cc783b7ecb0d71cb60961c99c2James Dong mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs); 2264c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2265c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 22663b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 22673b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 22685a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 22695a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 22705a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 22715a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 22725a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 22735a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 22745a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 22755a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2276c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 2277c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ALOGE("timestampUs %lld < lastTimestampUs %lld for %s track", 2278c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong timestampUs, lastTimestampUs, mIsAudio? "Audio": "Video"); 2279c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return UNKNOWN_ERROR; 22808c460498c028888c533ab442be12b6d4b669b965James Dong } 22818c460498c028888c533ab442be12b6d4b669b965James Dong 2282c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 2283c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 2284c059860c73678a202bfa33062723e8f82fb779d9James Dong 2285a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2286a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2287c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 228879761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2289be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2290be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2291be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2292be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2293965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2294be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2295be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2296c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2297be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2298be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 22998644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2300be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 23013856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld", 2302a472613aec322e25891abf5c77bf3f7e3c244920James Dong mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs); 23038644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2304c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 23058644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 230620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2307d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 2308c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 2309d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2310d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 231193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 231293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 231393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 231493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2315faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 231693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 231743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2318c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 231958ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 2320c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2321c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count = (mOwner->use32BitFileOffset() 2322c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 2323c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 2324c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2325c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (count == 0) { 23261f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 232758ae9c530247668f8af36e30d228c716c226b3d4James Dong } 232858ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 232958ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 233058ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 233158ae9c530247668f8af36e30d228c716c226b3d4James Dong } 233213aec890216948b0c364f8f92792129d0335f506James Dong 233313aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 233413aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 23351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 23361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 233713aec890216948b0c364f8f92792129d0335f506James Dong } else { 233813aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 233913aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 234013aec890216948b0c364f8f92792129d0335f506James Dong } else { 234143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 234243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 234343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 234443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 234543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 234613aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 234713aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 2348c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 2349c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 2350c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 235113aec890216948b0c364f8f92792129d0335f506James Dong } 23521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 235313aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 235413aec890216948b0c364f8f92792129d0335f506James Dong } 235513aec890216948b0c364f8f92792129d0335f506James Dong } 235613aec890216948b0c364f8f92792129d0335f506James Dong } 235713aec890216948b0c364f8f92792129d0335f506James Dong 235820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 235925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 236045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 2361690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2362f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 236345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2364bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2365be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 236613aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 236743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2368c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(1, mStszTableEntries->count()); 236958ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 23701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 23711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 237213aec890216948b0c364f8f92792129d0335f506James Dong } 237313aec890216948b0c364f8f92792129d0335f506James Dong 2374be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2375be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2376be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2377c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 1) { 23788f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 237979761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2380be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2381be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2382be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2383a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2384c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() <= 2) { 238579761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2386a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 238779761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2388a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2389a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 239079761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2391a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2392a472613aec322e25891abf5c77bf3f7e3c244920James Dong 239343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // The last ctts box may not have been written yet, and this 239443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // is to make sure that we write out the last ctts box. 239543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 239643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (cttsSampleCount > 0) { 239743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 239843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 239943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 240043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 2401c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 240225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 240343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 240443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 240543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2406df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 2407c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong count, nZeroLengthFrames, mStszTableEntries->count(), mIsAudio? "audio": "video"); 2408872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2409df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs()); 2410872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2411365a963142093a1cd8efdcea76b5f65096a5b115James Dong 241237187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 241337187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 241437187916a486504acaf83bea30147eb5fbf46ae5James Dong } 241537187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2416365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2417365a963142093a1cd8efdcea76b5f65096a5b115James Dong 241845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 2419c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { // no samples written 242029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 242145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 242245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 242345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2424c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (!mIsAudio && mStssTableEntries->count() == 0) { // no sync frames for video 242529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 242645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 242745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 242845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 242945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 243045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 243145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 243245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 243345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 243445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 243545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 243643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 243707ec01904613a0bac32caaa8444b4690998faed7James Dong 243807ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 243907ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 244007ec01904613a0bac32caaa8444b4690998faed7James Dong return; 244107ec01904613a0bac32caaa8444b4690998faed7James Dong } 244207ec01904613a0bac32caaa8444b4690998faed7James Dong 244343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 244443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 244543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 244643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 244743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mIsAudio? 0: 1); 244843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 244943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 245043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 245143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 245243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 245343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 245443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2455c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 245643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 245786b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 245886b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 245986b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 246086b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 246186b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 246286b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 246386b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 246486b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 246586b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 246686b7f47aa7482424cf8fd248f1315311919be3b0James Dong 246786b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 246870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 246970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 247086b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 247170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 247207ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 247307ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 247407ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 247507ec01904613a0bac32caaa8444b4690998faed7James Dong 247643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 247743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 247843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 247943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 248070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 248170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 248270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 248370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 248470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 248570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 248670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 248770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 248843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 248943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 249043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2491faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 24923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("trackProgressStatus: %lld us", timeUs); 2493c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2494215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 2495215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 24963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Fire time tracking progress status at %lld us", timeUs); 2497bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 249893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 249993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 250093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 250193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2502faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 2503bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 2504faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 2505bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 2506faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2507faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 2508faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 2509faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 2510bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2511bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2512faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2513faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 2514faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2515faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2516faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 2517faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 2518bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2519bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2520faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2521faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 2522faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 2523bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2524bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2525faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 2526faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2527faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 2528faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2529d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 25303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setDriftTimeUs: %lld us", driftTimeUs); 2531e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2532d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 2533e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2534e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2535e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 25363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 2537e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2538e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 2539e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2540e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2541de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghuibool MPEG4Writer::isRealTimeRecording() const { 2542de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui return mIsRealTimeRecording; 2543de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui} 2544de05c8eab188e98798f2b9c3dfac53dbc18ef584ztenghui 2545b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 2546b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 2547b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 2548b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 25491c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 25503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 25511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 25521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 25531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 255413aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 255520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 255620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 25573b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 2558c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 255920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 256020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2561d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2562d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 2563d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 2564d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2565690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 2566690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 2567690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2568690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2569690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2570690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2571690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2572690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 257329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 2574690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2575690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2576690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2577690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2578690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 257929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 2580690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2581690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2582690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2583690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2584690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2585690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 258720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 25883856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s track time scale: %d", 25891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 25908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 2591efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 2592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 2593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 2594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 2595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 2596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 2597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 2598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 2600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 2602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 2604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 2605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 2606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 2607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 2608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 2612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 2613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 2615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 2617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2618b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 2619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 2621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 2622965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong writeCttsBox(); 2623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mIsAudio) { 2624b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 2625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 2627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 2628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 2629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 2630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 2633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mp4v"); 2638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("s263"); 2640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avc1"); 2642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 264329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2661b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 2667c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->writeInt8(0); // compressor string length 2668c30a88a273b47bef6728ae1dddea11641090939aMartin Storsjo mOwner->write(" ", 31); 2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 2671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 267243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(23 + mCodecSpecificDataSize, 128); 2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 2676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 2678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *fourcc = NULL; 2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "samr"; 2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "sawb"; 2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "mp4a"; 2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 269829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 2706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 2709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 2711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 2716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 2717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 2721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 273143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 273443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(mCodecSpecificDataSize + 23, 128); 2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // max bit rate 2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // avg bit rate 2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 2767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 276843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 0x77, 0x00, 2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00, 2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00 2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2805efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2812219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 28148f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 2817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 282720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 2844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 2846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 2847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 2848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2853b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 2854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 2857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 2862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 2863b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 2865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 2870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2874efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 2875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 2876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 2877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 2881b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 2882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 2883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 2884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 2885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 2886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 2887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 2888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // language code 2889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 2895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 2901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 2907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 2910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 2914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 2916b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 2923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 2924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 292843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mCodecSpecificDataSize, 5); 2929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 2931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 2932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 2933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 2934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 2935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 2937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2938b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2939b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 2940b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 2941b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 2942b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2943b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 2944b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 2945b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 2946b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2947b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2948b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 2949b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 2950b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 2951b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2955b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2956000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 2957a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 2958b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 296043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 2961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2962b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2963000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 2964000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 2965000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2966000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 2967000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 2968000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 2969c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 2970c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mSttsTableEntries->get(duration, 1)); 2971c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back to host byte order 2972c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 2973c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 297620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2977965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 2978965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { // ctts is not for audio 2979965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 2980965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2981965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2982000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 2983000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 2984000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 2985000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2986000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2987965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 2988c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 2989965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 2990965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2991965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2992c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ALOGV("ctts box has %d entries with range [%lld, %lld]", 2993c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 2994965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2995965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 2996000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 2997c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 2998c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCttsTableEntries->get(duration, 1)); 2999c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back host byte order 3000c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1); 3001c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 3002965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 3003965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 3004965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 3005b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 3006b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 3007b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3008c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 3009b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 3010b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 301125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 3012b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 3013b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 3014b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3015c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 3016c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 3017b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 3018b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 301920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3020b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 3021b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 3022b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3023c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 3024b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 3025b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 302620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3027b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 3028b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 3029b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 3030c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 3031c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 3032c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 3033c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 3034b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 3035b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 303620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 303720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 303807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 303907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 304007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 304107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 304207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 304307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 304407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 304507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 304607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 304707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 304807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 304907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 305007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 305107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 305207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 3053432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 3054432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 305507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 305607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 305707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 305807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 305907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 306007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 306107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 306207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 306320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3064