MPEG4Writer.cpp revision 219f195159f93d627af2b243732e3f9020511a46
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; 461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongstatic const int64_t kMax32BitFileSize = 0x007fffffffLL; 473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07; 483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08; 4970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs = 700000LL; 505b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 53bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId); 548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 5837187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t stop(); 5937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 6025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 623b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 63d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 64b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTrackHeader(bool use32BitOffset = true); 651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 69c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong void addChunkOffset(off64_t offset); 7070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int32_t getTrackId() const { return mTrackId; } 71dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 74000e18370baae60ffd9f25b509501dd8c26deabfJames Dong enum { 75000e18370baae60ffd9f25b509501dd8c26deabfJames Dong kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 768c460498c028888c533ab442be12b6d4b669b965James Dong kSampleArraySize = 1000, 77000e18370baae60ffd9f25b509501dd8c26deabfJames Dong }; 78000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 79c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // A helper class to handle faster write box with table entries 80c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong template<class TYPE> 81c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong struct ListTableEntries { 82c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries(uint32_t elementCapacity, uint32_t entryCapacity) 83c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mElementCapacity(elementCapacity), 84c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEntryCapacity(entryCapacity), 85c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTotalNumTableEntries(0), 86c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry(0), 87c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement(NULL) { 88c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mElementCapacity, 0); 89c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(mEntryCapacity, 0); 90c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 91c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 92c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Free the allocated memory. 93c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ~ListTableEntries() { 94c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (!mTableEntryList.empty()) { 95c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 96c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete[] (*it); 97c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.erase(it); 98c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 99c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 100c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 101c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Replace the value at the given position by the given value. 102c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // There must be an existing value at the given position. 103c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order 104c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 105c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void set(const TYPE& value, uint32_t pos) { 10625f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong CHECK_LT(pos, mTotalNumTableEntries * mEntryCapacity); 107c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 108c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 109c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 110c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 111c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 112c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 114c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 115c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 116c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 117c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong (*it)[(pos % (mElementCapacity * mEntryCapacity))] = value; 118c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 119c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 120c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Get the value at the given position by the given value. 121c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value the retrieved value at the position in network byte order. 122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg pos location the value must be in. 123c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @return true if a value is found. 124c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool get(TYPE& value, uint32_t pos) const { 12525f0d7ba1987de61c75f8c68b19de48e0ad9736cJames Dong if (pos >= mTotalNumTableEntries * mEntryCapacity) { 126c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return false; 127c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 128c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 129c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong typename List<TYPE *>::iterator it = mTableEntryList.begin(); 130c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t iterations = (pos / (mElementCapacity * mEntryCapacity)); 131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong while (it != mTableEntryList.end() && iterations > 0) { 132c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++it; 133c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong --iterations; 134c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 135c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(it != mTableEntryList.end()); 136c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(iterations, 0); 137c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong value = (*it)[(pos % (mElementCapacity * mEntryCapacity))]; 139c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return true; 140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 141c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 142c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Store a single value. 143c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg value must be in network byte order. 144c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void add(const TYPE& value) { 145c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_LT(mNumValuesInCurrEntry, mElementCapacity); 146c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries % mElementCapacity; 147c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nValues = mNumValuesInCurrEntry % mEntryCapacity; 148c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries == 0 && nValues == 0) { 149c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement = new TYPE[mEntryCapacity * mElementCapacity]; 150c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCurrTableEntriesElement != NULL); 151c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mTableEntryList.push_back(mCurrTableEntriesElement); 152c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 153c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 154c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t pos = nEntries * mEntryCapacity + nValues; 155c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCurrTableEntriesElement[pos] = value; 156c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 157c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mNumValuesInCurrEntry; 158c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if ((mNumValuesInCurrEntry % mEntryCapacity) == 0) { 159c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ++mTotalNumTableEntries; 160c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mNumValuesInCurrEntry = 0; 161c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 162c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 163c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 164c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Write out the table entries: 165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 1. the number of entries goes first 166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // 2. followed by the values in the table enties in order 167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // @arg writer the writer to actual write to the storage 168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong void write(MPEG4Writer *writer) const { 169c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_EQ(mNumValuesInCurrEntry % mEntryCapacity, 0); 170c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t nEntries = mTotalNumTableEntries; 171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->writeInt32(nEntries); 172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong for (typename List<TYPE *>::iterator it = mTableEntryList.begin(); 173c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong it != mTableEntryList.end(); ++it) { 174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK_GT(nEntries, 0); 175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (nEntries >= mElementCapacity) { 176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, mElementCapacity); 177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong nEntries -= mElementCapacity; 178c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 179c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong writer->write(*it, sizeof(TYPE) * mEntryCapacity, nEntries); 180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong break; 181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 182c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 183c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 184c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong // Return the number of entries in the table. 186c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count() const { return mTotalNumTableEntries; } 187c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 188c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong private: 189c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mElementCapacity; // # entries in an element 190c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mEntryCapacity; // # of values in each entry 191c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mTotalNumTableEntries; 192c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t mNumValuesInCurrEntry; // up to mEntryCapacity 193c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong TYPE *mCurrTableEntriesElement; 194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mutable List<TYPE *> mTableEntryList; 195c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 196c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong DISALLOW_EVIL_CONSTRUCTORS(ListTableEntries); 197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong }; 198c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 199c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 200c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 203693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 205a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 206a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 207eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 2081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 2091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 2101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 211bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 212c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 21343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 214e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 215e259531ce59ab1f31de5a23124b22536f6a5a767James Dong bool mIsRealTimeRecording; 216d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 2171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 2188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 222be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 22313aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 2241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 225c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong bool mSamplesHaveSameSize; 226c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStszTableEntries; 227be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStcoTableEntries; 229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<off64_t> *mCo64TableEntries; 230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStscTableEntries; 231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mStssTableEntries; 232c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mSttsTableEntries; 233c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ListTableEntries<uint32_t> *mCttsTableEntries; 234965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 235000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMinCttsOffsetTimeUs; 236000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t mMaxCttsOffsetTimeUs; 237965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 2393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 2403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 2413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 2423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 2433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 2443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 2453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 2463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 2473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 2483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 2493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 2503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 2513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 254548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 25593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 25725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 2583c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 25970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 26070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 26193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 26293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 26325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 264872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 265872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 266872a481558350634a3fd5cb67939de288af00ecbJames Dong 267000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int32_t getStartTimeOffsetScaledTime() const; 268000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 27037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 2733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 2743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 275b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 276b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 278215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 279215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 280faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 28193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 28203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 28319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 28419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 285c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 286c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 287c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 288c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 289c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 290c059860c73678a202bfa33062723e8f82fb779d9James Dong 291690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 292690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 29313f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t mRotation; 294690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 2961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 2971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 29879761ab096f57c3027fad9556c2bc436672d614eJames Dong 29979761ab096f57c3027fad9556c2bc436672d614eJames Dong // Duration is time scale based 30079761ab096f57c3027fad9556c2bc436672d614eJames Dong void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 301965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 30245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 30345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong bool isTrackMalFormed() const; 30443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 3051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 307b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 309b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 310b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 311b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 312965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void writeCttsBox(); 313b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 314b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 318b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 319b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMdhdBox(time_t now); 321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 324b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTkhdBox(time_t now); 325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 336674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(-1), 337674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(NO_INIT), 338b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 3391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 340a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 341a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 342a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 343411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 34513aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 3467837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 34707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 34807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 34907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 35086b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 35186b7f47aa7482424cf8fd248f1315311919be3b0James Dong mStartTimeOffsetMs(-1) { 352674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong 353af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); 354674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mFd >= 0) { 355674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck = OK; 356674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong } 35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35930ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 360674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(dup(fd)), 361674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(mFd < 0? NO_INIT: OK), 362b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 3631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 364a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 365a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 366a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 367411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 36830ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 36913aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 3707837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 37107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 37207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 37307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 37486b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 37586b7f47aa7482424cf8fd248f1315311919be3b0James Dong mStartTimeOffsetMs(-1) { 37630ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 37730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 37820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 3798bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong reset(); 38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 3821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 3841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 3851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 390dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 391dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 392dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 393dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 394dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 395dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 396dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 397dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 398dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 399dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 400dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 401dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 402dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 403dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 404dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 405dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 406dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 407dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 408dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) const { 409dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 410dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 411dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 412dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 413dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 414dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 415dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 416dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 417c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); 41813210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 41913210f3346462a86ce9fe3af72a0c200dba84e27James Dong snprintf(buffer, SIZE, " duration encoded : %lld us\n", mTrackDurationUs); 42013210f3346462a86ce9fe3af72a0c200dba84e27James Dong result.append(buffer); 421dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 422dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 423dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 424dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 4252dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 426bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 427bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 42829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Attempt to add source AFTER recording is started"); 429bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 430bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 431219f195159f93d627af2b243732e3f9020511a46James Dong Track *track = new Track(this, source, 1 + mTracks.size()); 43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 4332dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 4342dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 43793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 438a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 439a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 44093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 441a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 442a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 443a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 444a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 445a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 446a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 447a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 448a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 449a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 450a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 451a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 452a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 453a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 4542dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 4552dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 4562dec2b5be2056c6d9428897dc672185872d30d17James Dong // 4572dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 4582dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 4592dec2b5be2056c6d9428897dc672185872d30d17James Dong 46078a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 4612dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 46278a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 4632dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 4642dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 4652dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 4662dec2b5be2056c6d9428897dc672185872d30d17James Dong 4672dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 4682dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 4692dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 47078a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 4712dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 4722dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 4732dec2b5be2056c6d9428897dc672185872d30d17James Dong 47478a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 475a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 47678a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 47778a1a286f736888ae7af8860b2c424af0d978848James Dong } 47878a1a286f736888ae7af8860b2c424af0d978848James Dong 47978a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 48078a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 48178a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 48278a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 48378a1a286f736888ae7af8860b2c424af0d978848James Dong ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000); 48478a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 48578a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 48678a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 48778a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 48878a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 48978a1a286f736888ae7af8860b2c424af0d978848James Dong } 49078a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 49178a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 49278a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 49378a1a286f736888ae7af8860b2c424af0d978848James Dong } 4942dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4952dec2b5be2056c6d9428897dc672185872d30d17James Dong } 49678a1a286f736888ae7af8860b2c424af0d978848James Dong 4972dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 4982dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 4992dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5002dec2b5be2056c6d9428897dc672185872d30d17James Dong 5012dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 5022dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 5032dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 5042dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 5052dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5062dec2b5be2056c6d9428897dc672185872d30d17James Dong 507df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 5082dec2b5be2056c6d9428897dc672185872d30d17James Dong " moov size %lld bytes", 5092dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 5102dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 5112dec2b5be2056c6d9428897dc672185872d30d17James Dong} 5122dec2b5be2056c6d9428897dc672185872d30d17James Dong 5132dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 514674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 51525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 518a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 519a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 520a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 521a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 522a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 523a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 524a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 525a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 526a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 527a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 5282dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 5292dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 5302dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 5312dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 5322dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 5332dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5342dec2b5be2056c6d9428897dc672185872d30d17James Dong 5351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 5361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 5371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 5381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 5391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 5401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 5411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 5421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 5431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 5445ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("32-bit file size limit (%lld bytes) too big. " 545d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong "It is changed to %lld bytes", 546d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 547d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 5481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 5491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 5501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 551b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 552b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 553b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 554b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 555b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 5562dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5572dec2b5be2056c6d9428897dc672185872d30d17James Dong 558065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 55993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 560a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 561a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 562a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 56393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 564a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 565a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 566a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 567a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 5688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 5698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 5708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 5718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 57243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 5733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("movie time scale: %d", mTimeScale); 5748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 57577e8ae9967a078770416619e99ddb5b010def312James Dong /* 57677e8ae9967a078770416619e99ddb5b010def312James Dong * When the requested file size limit is small, the priority 57777e8ae9967a078770416619e99ddb5b010def312James Dong * is to meet the file size limit requirement, rather than 57877e8ae9967a078770416619e99ddb5b010def312James Dong * to make the file streamable. 57977e8ae9967a078770416619e99ddb5b010def312James Dong */ 58077e8ae9967a078770416619e99ddb5b010def312James Dong mStreamableFile = 58177e8ae9967a078770416619e99ddb5b010def312James Dong (mMaxFileSizeLimitBytes != 0 && 58277e8ae9967a078770416619e99ddb5b010def312James Dong mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 58377e8ae9967a078770416619e99ddb5b010def312James Dong 58477e8ae9967a078770416619e99ddb5b010def312James Dong mWriteMoovBoxToMemory = mStreamableFile; 5857837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 5867837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 5877837c17063a4c50bc856ba59418516fdab731de7James Dong 588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5907837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5927837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 5932dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 5942dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 5952dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 5962dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5972dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 5987837c17063a4c50bc856ba59418516fdab731de7James Dong } 59943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mEstimatedMoovBoxSize, 8); 60077e8ae9967a078770416619e99ddb5b010def312James Dong if (mStreamableFile) { 60177e8ae9967a078770416619e99ddb5b010def312James Dong // Reserve a 'free' box only for streamable file 60277e8ae9967a078770416619e99ddb5b010def312James Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 60377e8ae9967a078770416619e99ddb5b010def312James Dong writeInt32(mEstimatedMoovBoxSize); 60477e8ae9967a078770416619e99ddb5b010def312James Dong write("free", 4); 60577e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 60677e8ae9967a078770416619e99ddb5b010def312James Dong } else { 60777e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mOffset; 60877e8ae9967a078770416619e99ddb5b010def312James Dong } 6097837c17063a4c50bc856ba59418516fdab731de7James Dong 6107837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 611c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 6121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 6131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 6141acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 6151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 6161acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 6171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 6191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 6201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 6211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 6221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 624a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 625a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 6271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 628a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 62925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 6331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 6341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 6351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 63637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 637674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 63837187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 639a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 640a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 64137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 642a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 643a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 64437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 64537187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 64637187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 64737187916a486504acaf83bea30147eb5fbf46ae5James Dong } 648a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 64937187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 650a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 651a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 6521c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 653b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping writer thread"); 654411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 655411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 656411ba422e3635d534928ffd81abf54f4f291c739James Dong } 6571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 6591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 6601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 6621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 6631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 6641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 6661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 667411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 668b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Writer thread stopped"); 6691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 6701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 67113f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 67213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 67313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 67413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 67513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 67613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 67713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 67813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 67913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 68013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 68113f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 68213f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 6833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeCompositionMatrix"); 68413f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 68513f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 68613f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 68713f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 68813f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 68913f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 69013f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 69113f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 69213f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 69313f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 69413f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 69513f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 69613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 69713f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 69813f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 69913f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 70013f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 70113f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 70213f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 70313f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 70413f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 70513f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 70613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 70713f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 70813f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 70913f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 71013f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 71113f6284305e4b27395a23db7882d670bdb1bcae1James Dong 71213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 71313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 71413f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 71513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 71613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 71713f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 71813f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 71913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 72013f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 72113f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 72213f6284305e4b27395a23db7882d670bdb1bcae1James Dong 723411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 724411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 725411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 726411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 727411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 728411ba422e3635d534928ffd81abf54f4f291c739James Dong} 72913f6284305e4b27395a23db7882d670bdb1bcae1James Dong 7308bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() { 731674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 73237187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 733411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 734411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 735411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 736411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 737411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 738411ba422e3635d534928ffd81abf54f4f291c739James Dong } 739411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 740411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 741411ba422e3635d534928ffd81abf54f4f291c739James Dong } 74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 7458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 74665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 74937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 75037187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 75137187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 75237187916a486504acaf83bea30147eb5fbf46ae5James Dong } 75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 7558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 7568f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 75865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 75965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 76065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 76165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 76265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 76365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 764b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Duration from tracks range is [%lld, %lld] us", 76565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 7697837c17063a4c50bc856ba59418516fdab731de7James Dong 77037187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 77137187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 772411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 77337187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 77437187916a486504acaf83bea30147eb5fbf46ae5James Dong } 77537187916a486504acaf83bea30147eb5fbf46ae5James Dong 77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 7771acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 778c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 7791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 780c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 7811acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 782c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 7831acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int64_t size = mOffset - mMdatOffset; 7841acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 785c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 7861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 787c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 789c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong const off64_t moovOffset = mOffset; 79077e8ae9967a078770416619e99ddb5b010def312James Dong mWriteMoovBoxToMemory = mStreamableFile; 7917837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 7927837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 7937837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7967837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 7977837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 79843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 7997837c17063a4c50bc856ba59418516fdab731de7James Dong 8007837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 801c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 8027837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 803674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 8047837c17063a4c50bc856ba59418516fdab731de7James Dong 8057837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 806c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 8077837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 8087837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 8097837c17063a4c50bc856ba59418516fdab731de7James Dong 8107837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 8117837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 8127837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 8137837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 8142dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 815df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("The mp4 file will not be streamable."); 8167837c17063a4c50bc856ba59418516fdab731de7James Dong } 8177837c17063a4c50bc856ba59418516fdab731de7James Dong 8180c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 820411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 82137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 85207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 85307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 85407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 8632cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); 875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 88007ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 88107ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 88207ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 88307ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 88407ec01904613a0bac32caaa8444b4690998faed7James Dong 88507ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 88607ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 88707ec01904613a0bac32caaa8444b4690998faed7James Dong char value[PROPERTY_VALUE_MAX]; 88807ec01904613a0bac32caaa8444b4690998faed7James Dong if (property_get("rw.media.record.test", value, NULL) && 88907ec01904613a0bac32caaa8444b4690998faed7James Dong (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 89007ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 89107ec01904613a0bac32caaa8444b4690998faed7James Dong } 89207ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 89307ec01904613a0bac32caaa8444b4690998faed7James Dong} 89407ec01904613a0bac32caaa8444b4690998faed7James Dong 89570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 89607ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 89707ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 89807ec01904613a0bac32caaa8444b4690998faed7James Dong return; 89907ec01904613a0bac32caaa8444b4690998faed7James Dong } 90007ec01904613a0bac32caaa8444b4690998faed7James Dong 90170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 90270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 90370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 90470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 90570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 90670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 90770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 90870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 90970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 91013aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 91113aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 91213aec890216948b0c364f8f92792129d0335f506James Dong return OK; 91313aec890216948b0c364f8f92792129d0335f506James Dong} 91413aec890216948b0c364f8f92792129d0335f506James Dong 91513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 91613aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 91713aec890216948b0c364f8f92792129d0335f506James Dong} 91813aec890216948b0c364f8f92792129d0335f506James Dong 91913aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 92013aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 92113aec890216948b0c364f8f92792129d0335f506James Dong} 92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 923c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 924c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 92520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 926c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 927c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 928c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 92920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 93320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 93503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 93603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 93703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 93803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 93903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 94003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 94103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 94203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 94303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 94403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 94503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 94603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 94703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 94803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 949c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 950c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 95130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 95230ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 95303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 954b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 955b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 956c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 957b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 958c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 959b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 960c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 961b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 962c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 963c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 964c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 965c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 966c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 967b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 968b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 969b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 97043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(length, 65536); 97130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 972b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 973c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 974b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 975c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 976c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 977b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 978b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 97930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 98030ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 98130ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 98230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 9837837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 984674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 9857837c17063a4c50bc856ba59418516fdab731de7James Dong 9867837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 9877837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 988674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong // This happens only when we write the moov box at the end of 989674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong // recording, not for each output video/audio frame we receive. 990c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 9911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 992c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 9937837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 9947837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 9957837c17063a4c50bc856ba59418516fdab731de7James Dong } 996674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 997674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 998674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 9997837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 10007837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 10017837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 10027837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 10037837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 10047837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = false; 10057837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 10067837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 10077837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 10087837c17063a4c50bc856ba59418516fdab731de7James Dong } 10097837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1010674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 10117837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 10127837c17063a4c50bc856ba59418516fdab731de7James Dong } 10137837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 10147837c17063a4c50bc856ba59418516fdab731de7James Dong} 10157837c17063a4c50bc856ba59418516fdab731de7James Dong 101620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 10170c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10197837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 10207837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 10270c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 102820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1029c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10327837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 10337837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 10347837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 10357837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1036c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 10377837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 10387837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1039c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 10407837c17063a4c50bc856ba59418516fdab731de7James Dong } 104120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 104220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 104320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1044674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 104720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 104820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1049674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 105020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 105120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 105220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 105320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1054674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 105720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 105820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1059674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 106020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 106320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1064674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 106620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 106720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 10680c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 1069674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 107020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 107120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 107207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 107307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 107407b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 107507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 107607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 107707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 107807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 107907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 108007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 108107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 108207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 108307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 108407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 108507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 108607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 108707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 108807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 108907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 109007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 109107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 109207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 109307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 109407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 109507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 109607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 109707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 109807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 109907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 110007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 110107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 110207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 110307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 110407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 110507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 110607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 110707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 110807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 110907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 111007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 111107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 111207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 111307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 111407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 111507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 111607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 111707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 111807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 111907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 112007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 112107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 112207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 112307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 112407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 112507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 112607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 112707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 112807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 112907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 113007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 113107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 113207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 113307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 113407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 113507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 113607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 113707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 113807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 113907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 114007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 114107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 114207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1144674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 114520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 114620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 114778a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 114878a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 114978a1a286f736888ae7af8860b2c424af0d978848James Dong} 115078a1a286f736888ae7af8860b2c424af0d978848James Dong 1151d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1152d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1153d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1154d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1155d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1156d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1157956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1158d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1159d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1160d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1161d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 11621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 116377e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 116477e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 116577e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 116677e8ae9967a078770416619e99ddb5b010def312James Dong } 1167acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1168acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1169acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1170acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1171d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1172d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1173d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1174d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1175d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1176d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1177d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1178d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1179d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1180d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1181d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1182d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1183d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1184d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1185d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1186d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1187d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 118825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 118925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 119025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 119125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 119225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 119325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 119425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 119525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 119625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 119725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 119825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 119925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 120025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1201f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1202df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("setStartTimestampUs: %lld", timeUs); 120343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 12043c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1205065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1206f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1207df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Earliest track starting time: %lld", mStartTimestampUs); 12083c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 12093c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 12103c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1211f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 12123c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 12133c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 12143c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 12153c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 121658ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 121758ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 121858ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 121958ae9c530247668f8af36e30d228c716c226b3d4James Dong} 122058ae9c530247668f8af36e30d228c716c226b3d4James Dong 122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 122320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1224bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 122625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1229a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1230a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1231eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1232bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1233c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1234956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1235be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1236c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)), 1239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)), 1240c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1241c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 1242c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 124320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 124425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1245548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 124613f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 124713f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 124819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 12498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 12501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 12511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 12521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 12531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 12541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 12551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 12561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1257c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1258c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1259c059860c73678a202bfa33062723e8f82fb779d9James Dong 12601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 12611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1262c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1263c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 1264c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 1265c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 12671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 126878a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 126978a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 127078a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 127178a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1272c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 127678a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 127778a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 127878a1a286f736888ae7af8860b2c424af0d978848James Dong } 12791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 12801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 12811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 12821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 12831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1284c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(chunkId)); 1285c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(sampleId)); 1286c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(1)); 12871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 12881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 12891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1290c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 12911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 12921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 12931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 129479761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 12951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 12965a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 12975ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("0-duration samples found: %d", sampleCount); 12985a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1299c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1300c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 13011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 13021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1303965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1304965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1305965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1306965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { 1307965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1308965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1309c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1310c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1311965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1312965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1313c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1314c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1315c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1316c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1317c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1318c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1319c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 13201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 13211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1322c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 13233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 1324c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1325c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1326c059860c73678a202bfa33062723e8f82fb779d9James Dong 1327c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1328c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1329c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1330c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1331c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1332c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1333c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1334c059860c73678a202bfa33062723e8f82fb779d9James Dong 1335c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1336c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1337c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1338c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1339c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1340c059860c73678a202bfa33062723e8f82fb779d9James Dong 134143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 134219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 134319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 134419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 134519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 134619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 134719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 134819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 134919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 135019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 135119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 135219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 135319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 135419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 135519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 135619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 135719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 135819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 135919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 136019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 136119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 136219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 136319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 136419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 136519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 136619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 136719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 136819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 136919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 137019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 137119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 137219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 137520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1378c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 1379c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 1380c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 1381c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 1382c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 1383c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 1384c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 1385c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 1386c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 1387c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 1388c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 1389c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 1390c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 1391c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 1392c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 1393c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 139720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 139820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 140093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 14013856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 140293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 140393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 140493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 140593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 140693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 140793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 14083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Receive request to track progress status for every %lld us", timeUs); 140993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 141093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 141193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 141293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 141393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 141493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 14151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 14161c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 14173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 14181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 14191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 14201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 14211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 14221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14231c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 14243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 14251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 14261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 14271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 14291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 14301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 14321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 14331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 14341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 14351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 14361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 14371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 143843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 14391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 14401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1441fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 14423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeChunkToFile: %lld from %s track", 14435410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video"); 1444fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1445fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1446fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1447fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1448fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1449fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong off64_t offset = chunk->mTrack->isAvc() 1450fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong ? addLengthPrefixedSample_l(*it) 1451fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1452fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1453fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1454fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1455fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 14561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 14571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 14591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1460fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 14611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1462fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 14631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 14641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1465fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 14663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 14671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 146870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 146970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1470e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 147170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 14721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 147370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 147470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 147570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 14761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 1477b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%d chunks are written in the last batch", outstandingChunks); 14781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 14791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1480fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 14813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 14821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 14841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 14851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 14861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 14871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 14881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 14891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 14901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 14911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 14921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 14931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 14941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 14951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 14973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 1498fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 14991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 15021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 15031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1504fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 15051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 15061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 15071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1508fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1509fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1510fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 151170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 151270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 151370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 151470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 151570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 151670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 151770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1518fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 15191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1521fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1522fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 15231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15251c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 15263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 15271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1528a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1529fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1530fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 15311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1532fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1533fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1534fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1535fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 15361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 15371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1539fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong // Actual write without holding the lock in order to 1540fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong // reduce the blocking time for media track threads. 1541fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 1542fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong mLock.unlock(); 1543fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 1544fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong mLock.lock(); 1545fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 15461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1547fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1548fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 15491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15511c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 15523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 15531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 15551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1556e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 15571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 15581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 15591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 15601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 156170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 156270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 15631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 15641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 15671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 15681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 15691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 15701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 1571411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 15721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 15731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 157693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1577a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1578a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1579a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1580a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1581a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 158225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 158393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 158419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 158519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 158619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 158770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 158819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 158913f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 159013f6284305e4b27395a23db7882d670bdb1bcae1James Dong if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 159113f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 159213f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 159313f6284305e4b27395a23db7882d670bdb1bcae1James Dong 15945b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong mIsRealTimeRecording = true; 1595e259531ce59ab1f31de5a23124b22536f6a5a767James Dong { 1596e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int32_t isNotRealTime; 1597e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) { 1598e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mIsRealTimeRecording = (isNotRealTime == 0); 1599e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1600e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1601e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 160293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 160393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1604f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1605a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (mIsRealTimeRecording && mOwner->numTracks() > 1) { 1606a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 1607a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 1608a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 1609a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 1610a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 1611a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 161286b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 161386b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 1614a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 161586b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 161686b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 161786b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 161886b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 161986b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 1620df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Start time offset: %lld us", startTimeOffsetUs); 1621a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 1622a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1623f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1624a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1625f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 162625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 162725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 162825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 162925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 163220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 163320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 163420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 163520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1636eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 1637c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 163825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1639956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 16401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 164143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 164220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 164325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 164420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 164525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 164625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 164720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 164820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 164937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1650a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 165137187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1652a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1653a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 165437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 1655b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping %s track", mIsAudio? "Audio": "Video"); 1656eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 165729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 1658eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 1659eaae38445a340c4857c1c5569475879a728e63b7James Dong } 1660eaae38445a340c4857c1c5569475879a728e63b7James Dong 166120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 166237187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 166320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 166420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 166520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 166620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 166720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 166820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 166937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = (status_t) dummy; 167037187916a486504acaf83bea30147eb5fbf46ae5James Dong 1671b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video"); 167237187916a486504acaf83bea30147eb5fbf46ae5James Dong { 167337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = mSource->stop(); 167437187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK && status != ERROR_END_OF_STREAM) { 167537187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 167637187916a486504acaf83bea30147eb5fbf46ae5James Dong } 167737187916a486504acaf83bea30147eb5fbf46ae5James Dong } 167837187916a486504acaf83bea30147eb5fbf46ae5James Dong 1679b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%s track stopped", mIsAudio? "Audio": "Video"); 168037187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 168120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 168220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 168325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 168425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 168525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 168625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 168720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 168820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 168920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 169020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 169137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 169237187916a486504acaf83bea30147eb5fbf46ae5James Dong return (void *) err; 169320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 169420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 16963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 16973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 16993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 17003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 17013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 17033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 17043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17053856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findNextStartCode: %p %d", data, length); 17063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 17083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 17093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 17103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 17113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 17133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 17143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 17163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 17173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 17193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 17203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17213856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 17223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 17233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 17243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 17263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 17273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 172829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 17293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 17303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 17333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 17343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 173529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 17363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 17373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 17393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 17403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 17413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 17423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 17433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 17443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 17453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 174629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 17473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 17483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 17513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 17523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 17533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 17553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 17563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 17583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 17593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 17603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 17623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 17633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 176429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Codec specific data length too short: %d", size); 17653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 17663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 17693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 17703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 17713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 17723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 17733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 17753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 17763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 17783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 17793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 17803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 17813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 17823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 17833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 17843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 17853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 17863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 17873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 17883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 17893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 17903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 17913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 17923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 179329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 17943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 17953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 17973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 17983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 18003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 18013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 180229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 18033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 18063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 18073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 18093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 181029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 18113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 18153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 18193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 18203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 18213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 18223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 18253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 18263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 18273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 182829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 18293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 183329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 18343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 18393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 18403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 18413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 184229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 18433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 184629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Too many pic parameter sets (%d) found", nPicParamSets); 18473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18501374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 18511374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 18521374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 18531374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 18543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 18553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 18563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 18573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 18583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 185929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 18603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 18613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18631374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 18643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 18653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 1866548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 186703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 186803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 1869548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 187003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 187129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 187203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 187303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 187403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 18753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 187629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Codec specific data length too short: %d", size); 187703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 187803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 187903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 18803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 18813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 18823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 188303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 188403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 18853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 188603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 188703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 188803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 18893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 18903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 189103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 189203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 18933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 18943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 18953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 18963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 189703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 18983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 1899b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 1900b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 1901b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 1902b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 1903b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 190403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 19063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 19073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 19083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 19093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 19103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 19113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 19123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 19133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 19223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 19233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 19253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 19293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 19303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 193603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 193703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 193803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 193903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1940872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 1941872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 1942872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 1943872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 1944872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 1945872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 1946872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 1947872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 1948872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 1949872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 1950872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 1951872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 1952872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 1953872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 1954872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1955872a481558350634a3fd5cb67939de288af00ecbJames Dong} 1956872a481558350634a3fd5cb67939de288af00ecbJames Dong 195737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 195830ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 195913aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 196043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 196113aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 196213aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 196313aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 1964965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 1965965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 1966965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 1967965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 1968965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 1969000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 1970a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 1971965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 1972000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 1973000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 1974000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 197543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 1976c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 1977e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1978a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 1979a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 1980a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } else { 1981a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 1982a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 198386106f8b0641444c97a39e9788eeef55ab2a2ac6Glenn Kasten androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 1984985f838934510983d8a887461e98dca60a6e858fJames Dong 1985d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 198620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 198793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 198820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 198993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 199020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 199120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 199220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 199313aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 199420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 199520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 199620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1997a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 1998a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 1999a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2000a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2001a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2002a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2003a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2004a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2005a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 200630ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 200730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 200803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 200903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 201003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 2011548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 2012548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 20131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 201403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 201503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 201603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 201703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 201843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_EQ((status_t)OK, err); 20191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 202003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 202103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 202203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 202303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 202403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 202503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 202630ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 202730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 202830ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 202930ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 203030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2031548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 203230ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2033a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2034a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2035d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2036d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2037d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2038d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2039d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2040d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2041d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2042d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2043d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2044d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 20451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 2046e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2047b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 2048b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mIsAvc) { 2049b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2050b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2051b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2052b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2053b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2054b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2055050b28a593350047845a45a14cc5026221ac1620James Dong 2056d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 20571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 20581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 20591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2060d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2061d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2062d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2063d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2064d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2065d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2066d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2067d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2068d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2069050b28a593350047845a45a14cc5026221ac1620James Dong 2070d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2071d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2072d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2073d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2074d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2075c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 207670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2077f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2078f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 20798428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 20803c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 208148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2082a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 20838428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 208443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(durExcludingEarlierPausesUs, 0ll); 20858428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 208643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(pausedDurationUs, lastDurationUs); 20878428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2088a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2089a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2090a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2091a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 209243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timestampUs, 0ll); 2093000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (!mIsAudio) { 2094965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2095965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2096965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2097000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 2098965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 2099965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 2100965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2101965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 2102000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 2103000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 210443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(cttsOffsetTimeUs, 0ll); 2105965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 2106000e18370baae60ffd9f25b509501dd8c26deabfJames Dong ALOGV("decoding time: %lld and ctts offset time: %lld", 2107000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 2108000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2109000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 2110000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 2111000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 211243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL); 2113c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 211443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 211543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 211643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 211743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 211843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 211943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 212043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 212143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 212243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 212343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 212443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 212543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 212643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 212743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 212843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 2129000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2130000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 2131c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 2132000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2133000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2134000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 2135000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2136000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2137000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2138000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2139000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2140000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2141000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2142965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2143872a481558350634a3fd5cb67939de288af00ecbJames Dong 2144872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsRealTimeRecording) { 2145872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2146872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 2147e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2148e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2149872a481558350634a3fd5cb67939de288af00ecbJames Dong 215043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timestampUs, 0ll); 21513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s media time stamp: %lld and previous paused duration %lld", 21528428af5381e835cc783b7ecb0d71cb60961c99c2James Dong mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs); 2153c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2154c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 21553b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 21563b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 21575a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 21585a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 21595a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 21605a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 21615a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 21625a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 21635a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 21645a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2165c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 2166c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ALOGE("timestampUs %lld < lastTimestampUs %lld for %s track", 2167c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong timestampUs, lastTimestampUs, mIsAudio? "Audio": "Video"); 2168c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return UNKNOWN_ERROR; 21698c460498c028888c533ab442be12b6d4b669b965James Dong } 21708c460498c028888c533ab442be12b6d4b669b965James Dong 2171c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 2172c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 2173c059860c73678a202bfa33062723e8f82fb779d9James Dong 2174a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2175a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 217779761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2178be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2179be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2180be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2181be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2182965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2183be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2184be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2186be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2187be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 21888644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2189be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 21903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld", 2191a472613aec322e25891abf5c77bf3f7e3c244920James Dong mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs); 21928644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2193c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 21948644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 219520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2196d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 2197c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 2198d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2199d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 220093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 220193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 220293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 220393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2204faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 220593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 220643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2207c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 220858ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 2209c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2210c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count = (mOwner->use32BitFileOffset() 2211c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 2212c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 2213c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2214c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (count == 0) { 22151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 221658ae9c530247668f8af36e30d228c716c226b3d4James Dong } 221758ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 221858ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 221958ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 222058ae9c530247668f8af36e30d228c716c226b3d4James Dong } 222113aec890216948b0c364f8f92792129d0335f506James Dong 222213aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 222313aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 22241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 22251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 222613aec890216948b0c364f8f92792129d0335f506James Dong } else { 222713aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 222813aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 222913aec890216948b0c364f8f92792129d0335f506James Dong } else { 223043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 223143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 223243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 223343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 223443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 223513aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 223613aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 2237c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 2238c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 2239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 224013aec890216948b0c364f8f92792129d0335f506James Dong } 22411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 224213aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 224313aec890216948b0c364f8f92792129d0335f506James Dong } 224413aec890216948b0c364f8f92792129d0335f506James Dong } 224513aec890216948b0c364f8f92792129d0335f506James Dong } 224613aec890216948b0c364f8f92792129d0335f506James Dong 224720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 224825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 224945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 2250690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2251f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 225245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2253bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2254be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 225513aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 225643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2257c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(1, mStszTableEntries->count()); 225858ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 22591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 22601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 226113aec890216948b0c364f8f92792129d0335f506James Dong } 226213aec890216948b0c364f8f92792129d0335f506James Dong 2263be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2264be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2265be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 1) { 22678f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 226879761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2269be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2270be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2271be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2272a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() <= 2) { 227479761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2275a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 227679761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2277a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2278a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 227979761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2280a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2281a472613aec322e25891abf5c77bf3f7e3c244920James Dong 228243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // The last ctts box may not have been written yet, and this 228343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // is to make sure that we write out the last ctts box. 228443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 228543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (cttsSampleCount > 0) { 228643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 228743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 228843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 228943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 2290c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 229125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 229243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 229343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 229443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2295df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 2296c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong count, nZeroLengthFrames, mStszTableEntries->count(), mIsAudio? "audio": "video"); 2297872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2298df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs()); 2299872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2300365a963142093a1cd8efdcea76b5f65096a5b115James Dong 230137187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 230237187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 230337187916a486504acaf83bea30147eb5fbf46ae5James Dong } 230437187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2305365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2306365a963142093a1cd8efdcea76b5f65096a5b115James Dong 230745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 2308c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { // no samples written 230929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 231045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 231145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 231245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2313c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (!mIsAudio && mStssTableEntries->count() == 0) { // no sync frames for video 231429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 231545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 231645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 231745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 231845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 231945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 232045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 232145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 232245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 232345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 232445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 232543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 232607ec01904613a0bac32caaa8444b4690998faed7James Dong 232707ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 232807ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 232907ec01904613a0bac32caaa8444b4690998faed7James Dong return; 233007ec01904613a0bac32caaa8444b4690998faed7James Dong } 233107ec01904613a0bac32caaa8444b4690998faed7James Dong 233243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 233343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 233443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 233543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 233643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mIsAudio? 0: 1); 233743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 233843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 233943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 234043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 234143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 234243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 234343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2344c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 234543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 234686b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 234786b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 234886b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 234986b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 235086b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 235186b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 235286b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 235386b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 235486b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 235586b7f47aa7482424cf8fd248f1315311919be3b0James Dong 235686b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 235770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 235870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 235986b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 236070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 236107ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 236207ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 236307ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 236407ec01904613a0bac32caaa8444b4690998faed7James Dong 236543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 236643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 236743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 236843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 236970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 237070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 237170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 237270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 237370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 237470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 237570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 237670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 237743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 237843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 237943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2380faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 23813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("trackProgressStatus: %lld us", timeUs); 2382c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2383215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 2384215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 23853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Fire time tracking progress status at %lld us", timeUs); 2386bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 238793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 238893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 238993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 239093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2391faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 2392bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 2393faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 2394bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 2395faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2396faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 2397faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 2398faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 2399bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2400bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2401faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2402faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 2403faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2404faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2405faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 2406faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 2407bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2408bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2409faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2410faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 2411faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 2412bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2413bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2414faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 2415faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2416faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 2417faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2418d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 24193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setDriftTimeUs: %lld us", driftTimeUs); 2420e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2421d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 2422e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2423e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2424e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 24253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 2426e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2427e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 2428e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2429e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2430b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 2431b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 2432b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 2433b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 24341c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 24353856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 24361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 24371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 24381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 243913aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 244020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 244120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24423b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 2443c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 244420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 244520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2446d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2447d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 2448d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 2449d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2450690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 2451690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 2452690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2453690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2454690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2455690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2456690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2457690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 245829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 2459690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2460690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2461690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2462690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2463690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 246429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 2465690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2466690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2467690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2468690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2469690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2470690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2471b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 247220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s track time scale: %d", 24741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 24758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 247620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 2477b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 2478b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 2479b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 2480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 2481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 2482b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 2483b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 2485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 2487b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 2489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 2490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 2491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 2492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 2493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 2497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 2498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 2500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2501b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 2502b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2503b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 2504b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 2506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 2507965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong writeCttsBox(); 2508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mIsAudio) { 2509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 2510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 2512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 2513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 2514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 2515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2516b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2517b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 2518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mp4v"); 2523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("s263"); 2525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avc1"); 2527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 252829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 2535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2537b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 2543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2546b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 2547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 2548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 2549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 2550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 2552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(" ", 32); 2553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 2554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 2555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 255643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(23 + mCodecSpecificDataSize, 128); 2557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2558b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 2560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2561b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 2562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2563b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 2564b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2565b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 2567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 2568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 2571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *fourcc = NULL; 2575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "samr"; 2577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "sawb"; 2579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "mp4a"; 2581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 258229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 2587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 2590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2591b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 2593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 2595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 2596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 2600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 2601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 2603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 2605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 2608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 2613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 261543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 261843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(mCodecSpecificDataSize + 23, 128); 2619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 2624b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 2625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 2630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 2632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // max bit rate 2634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // avg bit rate 2635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 265243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 2661b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 2666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 2668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 0x77, 0x00, 2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00, 2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00 2671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTkhdBox(time_t now) { 2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2696219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 26988f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 2706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 2707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 271120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 2718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMdhdBox(time_t now) { 2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 2767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // language code 2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 281243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mCodecSpecificDataSize, 5); 2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 2817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 2821b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 2829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2840000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 2841a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 284443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2847000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 2848000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 2849000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2850000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 2851000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 2852000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 2853c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 2854c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mSttsTableEntries->get(duration, 1)); 2855c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back to host byte order 2856c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 2857c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 2858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 2859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 286020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2861965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 2862965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { // ctts is not for audio 2863965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 2864965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2865965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2866000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 2867000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 2868000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 2869000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2870000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2871965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 2872c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 2873965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 2874965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2875965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2876c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ALOGV("ctts box has %d entries with range [%lld, %lld]", 2877c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 2878965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2879965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 2880000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 2881c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 2882c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCttsTableEntries->get(duration, 1)); 2883c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back host byte order 2884c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1); 2885c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 2886965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 2887965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 2888965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2892c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 289525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2899c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 2900c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 2901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 2902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 290320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2907c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 2909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 291020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 2912b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2914c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 2915c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 2916c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 2917c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 292020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 292120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 292207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 292307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 292407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 292507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 292607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 292707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 292807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 292907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 293007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 293107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 293207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 293307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 293407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 293507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 293607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 2937432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 2938432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 293907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 294007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 294107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 294207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 294307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 294407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 294507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 294607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 294720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 2948