MPEG4Writer.cpp revision 7b670d4a0a4fa560f536f132e0a3fc7247f6724c
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(); 320efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeMdhdBox(uint32_t now); 321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 324efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson void writeTkhdBox(uint32_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 5787b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to make the file streamable. mStreamableFile does not tell 5797b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * whether the actual recorded file is streamable or not. 58077e8ae9967a078770416619e99ddb5b010def312James Dong */ 58177e8ae9967a078770416619e99ddb5b010def312James Dong mStreamableFile = 58277e8ae9967a078770416619e99ddb5b010def312James Dong (mMaxFileSizeLimitBytes != 0 && 58377e8ae9967a078770416619e99ddb5b010def312James Dong mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 58477e8ae9967a078770416619e99ddb5b010def312James Dong 5857b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong /* 5867b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory is true if the amount of data in moov box is 5877b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * smaller than the reserved free space at the beginning of a file, AND 5887b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * when the content of moov box is constructed. Note that video/audio 5897b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * frame data is always written to the file but not in the memory. 5907b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 5917b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Before stop()/reset() is called, mWriteMoovBoxToMemory is always 5927b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * false. When reset() is called at the end of a recording session, 5937b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * Moov box needs to be constructed. 5947b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 5957b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory 5967b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to set to mStreamableFile so that if 5977b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the file is intended to be streamable, it is set to true; 5987b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * otherwise, it is set to false. When the value is set to false, 5997b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * all the content of the moov box is written immediately to 6007b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * the end of the file. When the value is set to true, all the 6017b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * content of the moov box is written to an in-memory cache, 6027b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mMoovBoxBuffer, util the following condition happens. Note 6037b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * that the size of the in-memory cache is the same as the 6047b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * reserved free space at the beginning of the file. 6057b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6067b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 2) While the data of the moov box is written to an in-memory 6077b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache, the data size is checked against the reserved space. 6087b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * If the data size surpasses the reserved space, subsequent moov 6097b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * data could no longer be hold in the in-memory cache. This also 6107b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * indicates that the reserved space was too small. At this point, 6117b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * _all_ moov data must be written to the end of the file. 6127b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * mWriteMoovBoxToMemory must be set to false to direct the write 6137b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * to the file. 6147b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 6157b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * 3) If the data size in moov box is smaller than the reserved 6167b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space after moov box is completely constructed, the in-memory 6177b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * cache copy of the moov box is written to the reserved free 6187b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * space. Thus, immediately after the moov is completedly 6197b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong * constructed, mWriteMoovBoxToMemory is always set to false. 6207b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong */ 6217b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 6227837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 6237837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 6247837c17063a4c50bc856ba59418516fdab731de7James Dong 625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6277837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6297837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 6302dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 6312dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 6322dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 6332dec2b5be2056c6d9428897dc672185872d30d17James Dong } 6342dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 6357837c17063a4c50bc856ba59418516fdab731de7James Dong } 63643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mEstimatedMoovBoxSize, 8); 63777e8ae9967a078770416619e99ddb5b010def312James Dong if (mStreamableFile) { 63877e8ae9967a078770416619e99ddb5b010def312James Dong // Reserve a 'free' box only for streamable file 63977e8ae9967a078770416619e99ddb5b010def312James Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 64077e8ae9967a078770416619e99ddb5b010def312James Dong writeInt32(mEstimatedMoovBoxSize); 64177e8ae9967a078770416619e99ddb5b010def312James Dong write("free", 4); 64277e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 64377e8ae9967a078770416619e99ddb5b010def312James Dong } else { 64477e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mOffset; 64577e8ae9967a078770416619e99ddb5b010def312James Dong } 6467837c17063a4c50bc856ba59418516fdab731de7James Dong 6477837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 648c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 6491acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 6501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 6511acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 6521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 6531acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 6541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 6561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 6571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 6581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 6591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 661a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 662a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 6641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 665a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 66625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 6701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 6711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 6721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 67337187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 674674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 67537187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 676a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 677a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 67837187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 679a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 680a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 68137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 68237187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 68337187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 68437187916a486504acaf83bea30147eb5fbf46ae5James Dong } 685a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 68637187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 687a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 688a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 6891c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 690b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping writer thread"); 691411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 692411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 693411ba422e3635d534928ffd81abf54f4f291c739James Dong } 6941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 6961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 6971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 6991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 7001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 7011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 7031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 704411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 705b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Writer thread stopped"); 7061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 7071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 70813f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 70913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 71013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 71113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 71213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 71313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 71413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 71513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 71613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 71713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 71813f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 71913f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 7203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeCompositionMatrix"); 72113f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 72213f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 72313f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 72413f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 72513f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 72613f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 72713f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 72813f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 72913f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 73013f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 73113f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 73213f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 73313f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 73413f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 73513f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 73613f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 73713f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 73813f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 73913f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 74013f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 74113f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 74213f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 74313f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 74413f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 74513f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 74613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 74713f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 74813f6284305e4b27395a23db7882d670bdb1bcae1James Dong 74913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 75013f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 75113f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 75213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 75313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 75413f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 75513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 75613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 75713f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 75813f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 75913f6284305e4b27395a23db7882d670bdb1bcae1James Dong 760411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 761411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 762411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 763411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 764411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 765411ba422e3635d534928ffd81abf54f4f291c739James Dong} 76613f6284305e4b27395a23db7882d670bdb1bcae1James Dong 7678bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() { 768674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 76937187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 770411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 771411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 772411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 773411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 774411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 775411ba422e3635d534928ffd81abf54f4f291c739James Dong } 776411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 777411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 778411ba422e3635d534928ffd81abf54f4f291c739James Dong } 77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 7828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 78365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 78637187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 78737187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 78837187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 78937187916a486504acaf83bea30147eb5fbf46ae5James Dong } 79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 7928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 7938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 79565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 79665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 79765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 79865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 79965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 80065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 801b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Duration from tracks range is [%lld, %lld] us", 80265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 80320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 8067837c17063a4c50bc856ba59418516fdab731de7James Dong 80737187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 80837187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 809411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 81037187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 81137187916a486504acaf83bea30147eb5fbf46ae5James Dong } 81237187916a486504acaf83bea30147eb5fbf46ae5James Dong 81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 8141acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 815c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 8161acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 817c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 8181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 819c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 8201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int64_t size = mOffset - mMdatOffset; 8211acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 822c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 8231acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 824c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8267b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Construct moov box now 8277837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 8287b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = mStreamableFile; 8297b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 8307b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // There is no need to allocate in-memory cache 8317b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // for moov box if the file is not streamable. 8327b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 8337b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 8347b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong CHECK(mMoovBoxBuffer != NULL); 8357b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 83720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8387b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // mWriteMoovBoxToMemory could be set to false in 8397b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // MPEG4Writer::write() method 8407b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mWriteMoovBoxToMemory) { 8417b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong mWriteMoovBoxToMemory = false; 8427b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Content of the moov box is saved in the cache, and the in-memory 8437b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // moov box needs to be written to the file in a single shot. 8447b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 84543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 8467837c17063a4c50bc856ba59418516fdab731de7James Dong 8477837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 848c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 8497837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 850674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 8517837c17063a4c50bc856ba59418516fdab731de7James Dong 8527837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 853c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 8547837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 8557837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 8567b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } else { 8577b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ALOGI("The mp4 file will not be streamable."); 8587b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong } 8597837c17063a4c50bc856ba59418516fdab731de7James Dong 8607b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // Free in-memory cache for moov box 8617b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong if (mMoovBoxBuffer != NULL) { 8627837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 8637837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 8647837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 8657837c17063a4c50bc856ba59418516fdab731de7James Dong } 8667837c17063a4c50bc856ba59418516fdab731de7James Dong 8670c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 869411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 87037187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 87120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 87220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 873efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() { 874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 875efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 876efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // while time function returns Unix epoch values which starts 877efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // at 1970-01-01. Lets add the number of seconds between them 878efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60); 879efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson return mpeg4Time; 880efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson} 881efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson 882efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 883efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 904b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 91007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 91107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 91207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 916b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 919b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 9212cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 923b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 924b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 925b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 926b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 929b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 930b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 931b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 932b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); 933b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 934b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 935b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 936b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 937b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 93807ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 93907ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 94007ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 94107ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 94207ec01904613a0bac32caaa8444b4690998faed7James Dong 94307ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 94407ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 94507ec01904613a0bac32caaa8444b4690998faed7James Dong char value[PROPERTY_VALUE_MAX]; 94607ec01904613a0bac32caaa8444b4690998faed7James Dong if (property_get("rw.media.record.test", value, NULL) && 94707ec01904613a0bac32caaa8444b4690998faed7James Dong (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 94807ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 94907ec01904613a0bac32caaa8444b4690998faed7James Dong } 95007ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 95107ec01904613a0bac32caaa8444b4690998faed7James Dong} 95207ec01904613a0bac32caaa8444b4690998faed7James Dong 95370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 95407ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 95507ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 95607ec01904613a0bac32caaa8444b4690998faed7James Dong return; 95707ec01904613a0bac32caaa8444b4690998faed7James Dong } 95807ec01904613a0bac32caaa8444b4690998faed7James Dong 95970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 96070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 96170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 96270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 96370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 96470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 96570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 96670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 96770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 96813aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 96913aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 97013aec890216948b0c364f8f92792129d0335f506James Dong return OK; 97113aec890216948b0c364f8f92792129d0335f506James Dong} 97213aec890216948b0c364f8f92792129d0335f506James Dong 97313aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 97413aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 97513aec890216948b0c364f8f92792129d0335f506James Dong} 97613aec890216948b0c364f8f92792129d0335f506James Dong 97713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 97813aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 97913aec890216948b0c364f8f92792129d0335f506James Dong} 98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 981c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 982c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 984c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 985c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 986c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 98820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 98920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 99020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 99120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 99220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 99303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 99403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 99503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 99603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 99703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 99803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 99903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 100003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 100103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 100203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 100303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 100403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 100503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 100603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1007c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 1008c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 100930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 101030ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 101103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1012b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 1013b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 1014c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1015b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 1016c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1017b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 1018c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1019b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1020c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1021c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 1022c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 1023c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 1024c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 1025b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1026b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 1027b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 102843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(length, 65536); 102930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1030b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 1031c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1032b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 1033c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 1034c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 1035b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 1036b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 103730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 103830ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 103930ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 104030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 10417837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 1042674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 10437837c17063a4c50bc856ba59418516fdab731de7James Dong 10447837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 10457837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 10467b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 1047c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 10481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 10497b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // The reserved moov box at the beginning of the file 10507b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // is not big enough. Moov box should be written to 10517b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the end of the file from now on, but not to the 10527b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // in-memory cache. 10537b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 10547b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // We write partial moov box that is in the memory to 10557b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // the file first. 1056c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 10577837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 10587837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 10597837c17063a4c50bc856ba59418516fdab731de7James Dong } 1060674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 1061674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 10627b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong ::write(mFd, ptr, bytes); 10637837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 10647b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong 10657b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // All subsequent moov box content will be written 10667b670d4a0a4fa560f536f132e0a3fc7247f6724cJames Dong // to the end of the file. 10677837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 10687837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 10697837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 10707837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 10717837c17063a4c50bc856ba59418516fdab731de7James Dong } 10727837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1073674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 10747837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 10757837c17063a4c50bc856ba59418516fdab731de7James Dong } 10767837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 10777837c17063a4c50bc856ba59418516fdab731de7James Dong} 10787837c17063a4c50bc856ba59418516fdab731de7James Dong 107920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 10800c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 108120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10827837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 10837837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 108420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 108520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 108620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 108720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 108820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 108920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 10900c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 109120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1092c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 109320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 109420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10957837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 10967837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 10977837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 10987837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1099c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 11007837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 11017837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1102c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 11037837c17063a4c50bc856ba59418516fdab731de7James Dong } 110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 110520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1107674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1112674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 111320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 111420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 111620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1117674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 111820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 112020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1122674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 112320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 112420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 112520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 112620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1127674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 112920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 113020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 11310c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 1132674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 113420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 113507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 113607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 113707b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 113807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 113907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 114007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 114107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 114207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 114307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 114407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 114507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 114607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 114707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 114807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 114907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 115007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 115107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 115207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 115307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 115407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 115507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 115607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 115707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 115807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 115907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 116007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 116107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 116207b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 116307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 116407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 116507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 116607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 116707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 116807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 116907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 117007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 117107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 117207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 117307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 117407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 117507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 117607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 117707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 117807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 117907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 118007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 118107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 118207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 118307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 118407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 118507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 118607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 118707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 118807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 118907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 119007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 119107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 119207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 119307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 119407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 119507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 119607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 119707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 119807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 119907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 120007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 120107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 120207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 120307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 120407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 120507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1207674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121078a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 121178a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 121278a1a286f736888ae7af8860b2c424af0d978848James Dong} 121378a1a286f736888ae7af8860b2c424af0d978848James Dong 1214d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1215d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1216d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1217d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1218d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1219d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1220956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1221d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1222d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1223d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1224d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 12251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 122677e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 122777e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 122877e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 122977e8ae9967a078770416619e99ddb5b010def312James Dong } 1230acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1231acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1232acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1233acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1234d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1235d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1236d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1237d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1238d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1239d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1240d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1241d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1242d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1243d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1244d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1245d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1246d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1247d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1248d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1249d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1250d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 125125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 125225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 125325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 125425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 125525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 125625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 125725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 125825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 125925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 126025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 126125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 126225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 126325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1264f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1265df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("setStartTimestampUs: %lld", timeUs); 126643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 12673c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1268065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1269f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1270df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Earliest track starting time: %lld", mStartTimestampUs); 12713c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 12723c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 12733c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1274f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 12753c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 12763c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 12773c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 12783c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 127958ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 128058ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 128158ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 128258ae9c530247668f8af36e30d228c716c226b3d4James Dong} 128358ae9c530247668f8af36e30d228c716c226b3d4James Dong 128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 128620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1287bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 128925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1292a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1293a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1294eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1295bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1296c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1297956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1298be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1299c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1300c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1301c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)), 1302c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)), 1303c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1304c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 1305c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 130620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 130725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1308548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 130913f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 131013f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 131119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 13128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 13131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 13141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 13151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 13161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 13171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 13181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 13191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1320c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1321c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1322c059860c73678a202bfa33062723e8f82fb779d9James Dong 13231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 13241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1325c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1326c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 1327c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 1328c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1329c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 13301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 133178a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 133278a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 133378a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 133478a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1335c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1336c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1337c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1338c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 133978a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 134078a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 134178a1a286f736888ae7af8860b2c424af0d978848James Dong } 13421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 13431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 13441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 13451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 13461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1347c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(chunkId)); 1348c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(sampleId)); 1349c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(1)); 13501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 13511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 13521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1353c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 13541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 13551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 13561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 135779761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 13581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 13595a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 13605ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("0-duration samples found: %d", sampleCount); 13615a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1362c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1363c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 13641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 13651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1366965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1367965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1368965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1369965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { 1370965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1371965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1372c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1373c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1374965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1375965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1376c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1377c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1378c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1379c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1380c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1381c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1382c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 13831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 13841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1385c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 13863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 1387c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1388c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1389c059860c73678a202bfa33062723e8f82fb779d9James Dong 1390c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1391c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1392c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1393c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1394c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1395c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1396c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1397c059860c73678a202bfa33062723e8f82fb779d9James Dong 1398c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1399c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1400c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1401c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1402c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1403c059860c73678a202bfa33062723e8f82fb779d9James Dong 140443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 140519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 140619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 140719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 140819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 140919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 141019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 141119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 141219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 141319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 141419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 141519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 141619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 141719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 141819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 141919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 142019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 142119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 142219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 142319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 142419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 142519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 142619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 142719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 142819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 142919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 143019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 143119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 143219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 143319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 143419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 143519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 143820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 143920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1441c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 1442c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 1443c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 1444c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 1445c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 1446c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 1447c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 1448c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 1449c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 1450c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 1451c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 1452c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 1453c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 1454c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 1455c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 1456c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 145720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 145820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 145920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 146020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 146393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 14643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 146593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 146693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 146793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 146893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 146993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 147093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 14713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Receive request to track progress status for every %lld us", timeUs); 147293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 147393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 147493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 147593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 147693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 147793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 14781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 14791c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 14803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 14811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 14821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 14831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 14841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 14851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14861c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 14873856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 14881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 14891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 14901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 14921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 14931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 14951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 14961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 14971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 14981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 14991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 150143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 15021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1504fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 15053856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeChunkToFile: %lld from %s track", 15065410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video"); 1507fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1508fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1509fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1510fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1511fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1512fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong off64_t offset = chunk->mTrack->isAvc() 1513fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong ? addLengthPrefixedSample_l(*it) 1514fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1515fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1516fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1517fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1518fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 15191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 15221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1523fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 15241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1525fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 15261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1528fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 15293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 15301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 153170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 153270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1533e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 153470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 15351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 153670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 153770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 153870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 15391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 1540b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%d chunks are written in the last batch", outstandingChunks); 15411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1543fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 15443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 15451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 15471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 15481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 15491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 15501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 15511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 15521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 15531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 15541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 15551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 15603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 1561fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 15621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 15651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 15661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1567fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 15681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 15691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 15701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1571fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1572fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1573fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 157470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 157570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 157670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 157770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 157870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 157970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 158070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1581fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 15821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1584fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1585fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 15861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15881c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 15893856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 15901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1591a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1592fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1593fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 15941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1595fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1596fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1597fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1598fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 15991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 16001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1602fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong // Actual write without holding the lock in order to 1603fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong // reduce the blocking time for media track threads. 1604fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 1605fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong mLock.unlock(); 1606fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 1607fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong mLock.lock(); 1608fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 16091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1610fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1611fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 16121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16141c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 16153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 16161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 16181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1619e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 16201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 16211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 16221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 16231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 162470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 162570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 16261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 16271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 16281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 16301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 16311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 16321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 16331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 1634411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 16351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 16361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 16371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 16381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 163993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1640a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1641a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1642a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1643a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1644a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 164525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 164693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 164719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 164819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 164919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 165070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 165119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 165213f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 165313f6284305e4b27395a23db7882d670bdb1bcae1James Dong if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 165413f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 165513f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 165613f6284305e4b27395a23db7882d670bdb1bcae1James Dong 16575b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong mIsRealTimeRecording = true; 1658e259531ce59ab1f31de5a23124b22536f6a5a767James Dong { 1659e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int32_t isNotRealTime; 1660e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) { 1661e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mIsRealTimeRecording = (isNotRealTime == 0); 1662e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1663e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1664e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 166593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 166693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1667f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1668a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (mIsRealTimeRecording && mOwner->numTracks() > 1) { 1669a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 1670a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 1671a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 1672a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 1673a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 1674a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 167586b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 167686b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 1677a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 167886b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 167986b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 168086b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 168186b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 168286b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 1683df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Start time offset: %lld us", startTimeOffsetUs); 1684a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 1685a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1686f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1687a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1688f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 168925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 169025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 169125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 169225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 169320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 169420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 169520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 169620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 169720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 169820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1699eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 1700c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 170125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1702956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 17031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 170443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 170520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 170625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 170720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 170825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 170925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 171020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 171120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 171237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1713a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 171437187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1715a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1716a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 171737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 1718b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping %s track", mIsAudio? "Audio": "Video"); 1719eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 172029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 1721eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 1722eaae38445a340c4857c1c5569475879a728e63b7James Dong } 1723eaae38445a340c4857c1c5569475879a728e63b7James Dong 172420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 172537187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 172620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 172720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 172820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 172920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 173020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 173120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 173237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = (status_t) dummy; 173337187916a486504acaf83bea30147eb5fbf46ae5James Dong 1734b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video"); 173537187916a486504acaf83bea30147eb5fbf46ae5James Dong { 173637187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = mSource->stop(); 173737187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK && status != ERROR_END_OF_STREAM) { 173837187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 173937187916a486504acaf83bea30147eb5fbf46ae5James Dong } 174037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 174137187916a486504acaf83bea30147eb5fbf46ae5James Dong 1742b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%s track stopped", mIsAudio? "Audio": "Video"); 174337187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 174420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 174520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 174625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 174725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 174825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 174925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 175020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 175120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 175220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 175320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 175437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 175537187916a486504acaf83bea30147eb5fbf46ae5James Dong return (void *) err; 175620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 175720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 17593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 17603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 17623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 17633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 17643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 17663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 17673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findNextStartCode: %p %d", data, length); 17693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 17713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 17723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 17733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 17743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 17763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 17773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 17793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 17803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 17823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 17833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 17853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 17863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 17873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 17893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 17903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 179129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 17923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 17933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 17963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 17973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 179829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 17993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 18003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 18023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 18033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 18043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 18053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 18063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 18073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 18083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 180929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 18103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 18113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 18143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 18153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 18163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 18183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 18213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 18223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 18233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 18253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 18263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 182729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Codec specific data length too short: %d", size); 18283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 18323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 18333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 18343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 18353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 18363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 18383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 18393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18403856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 18413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 18423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 18433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 18443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 18453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 18463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 18473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 18483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 18493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 18503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 18513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 18523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 18533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 18543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 18553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 185629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 18573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 18603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 18613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 18633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 18643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 186529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 18663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 18693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 18703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 18723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 187329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 18743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 18783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 18823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 18833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 18843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 18853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 18883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 18893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 18903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 189129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 18923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 189629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 18973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 19023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 19033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 19043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 190529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 19063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 190929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Too many pic parameter sets (%d) found", nPicParamSets); 19103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 19113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19131374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 19141374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 19151374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 19161374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 19203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 192229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 19233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19261374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 1929548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 193003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 193103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 1932548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 193303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 193429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 193503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 193603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 193703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 193929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Codec specific data length too short: %d", size); 194003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 194103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 194203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 19453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 194603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 194703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 194903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 195003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 195103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 19533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 195403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 195503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 19563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 19573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 19583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 19593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 196003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 1962b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 1963b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 1964b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 1965b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 1966b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 196703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 19693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 19703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 19713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 19723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 19733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 19743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 19753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 19763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 19773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 19783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 19803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 19813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 19823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 19853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 19863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 19873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 19883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 19893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 19903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 19913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 19923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 19933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 19943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 19963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 19973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 19983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 199903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 200003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 200103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 200203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 2003872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 2004872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 2005872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 2006872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 2007872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 2008872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 2009872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 2010872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 2011872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 2012872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 2013872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 2014872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 2015872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 2016872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 2017872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2018872a481558350634a3fd5cb67939de288af00ecbJames Dong} 2019872a481558350634a3fd5cb67939de288af00ecbJames Dong 202037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 202130ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 202213aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 202343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 202413aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 202513aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 202613aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 2027965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 2028965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 2029965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 2030965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 2031965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 2032000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 2033a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 2034965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 2035000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 2036000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 2037000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 203843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 2039c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 2040e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2041a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 2042a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 2043a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } else { 2044a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 2045a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 204686106f8b0641444c97a39e9788eeef55ab2a2ac6Glenn Kasten androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 2047985f838934510983d8a887461e98dca60a6e858fJames Dong 2048d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 204920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 205093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 205120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 205293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 205320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 205420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 205520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 205613aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 205720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 205820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 205920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2060a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 2061a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 2062a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2063a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2064a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2065a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2066a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2067a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2068a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 206930ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 207030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 207103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 207203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 207303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 2074548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 2075548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 20761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 207703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 207803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 207903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 208003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 208143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_EQ((status_t)OK, err); 20821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 208303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 208403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 208503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 208603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 208703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 208803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 208930ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 209030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 209130ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 209230ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 209330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2094548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 209530ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2096a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2097a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2098d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2099d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2100d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2101d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2102d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2103d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2104d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2105d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2106d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2107d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 21081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 2109e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2110b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 2111b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mIsAvc) { 2112b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2113b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2114b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2115b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2116b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2117b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2118050b28a593350047845a45a14cc5026221ac1620James Dong 2119d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 21201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 21211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 21221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2123d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2124d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2125d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2126d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2127d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2128d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2129d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2130d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2131d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2132050b28a593350047845a45a14cc5026221ac1620James Dong 2133d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2134d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2135d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2136d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2137d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2138c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 213970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2140f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2141f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 21428428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 21433c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 214448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2145a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 21468428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 214743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(durExcludingEarlierPausesUs, 0ll); 21488428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 214943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(pausedDurationUs, lastDurationUs); 21508428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2151a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2152a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2153a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2154a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 215543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timestampUs, 0ll); 2156000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (!mIsAudio) { 2157965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2158965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2159965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2160000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 2161965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 2162965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 2163965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2164965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 2165000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 2166000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 216743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(cttsOffsetTimeUs, 0ll); 2168965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 2169000e18370baae60ffd9f25b509501dd8c26deabfJames Dong ALOGV("decoding time: %lld and ctts offset time: %lld", 2170000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 2171000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2172000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 2173000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 2174000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 217543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL); 2176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 217743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 217843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 217943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 218043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 218143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 218243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 218343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 218443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 218543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 218643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 218743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 218843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 218943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 219043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 219143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 2192000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2193000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 2194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 2195000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2196000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2197000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 2198000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2199000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2200000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2201000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2202000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2203000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2204000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2205965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2206872a481558350634a3fd5cb67939de288af00ecbJames Dong 2207872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsRealTimeRecording) { 2208872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2209872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 2210e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2211e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2212872a481558350634a3fd5cb67939de288af00ecbJames Dong 221343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timestampUs, 0ll); 22143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s media time stamp: %lld and previous paused duration %lld", 22158428af5381e835cc783b7ecb0d71cb60961c99c2James Dong mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs); 2216c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2217c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 22183b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 22193b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 22205a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 22215a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 22225a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 22235a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 22245a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 22255a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 22265a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 22275a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2228c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 2229c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ALOGE("timestampUs %lld < lastTimestampUs %lld for %s track", 2230c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong timestampUs, lastTimestampUs, mIsAudio? "Audio": "Video"); 2231c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return UNKNOWN_ERROR; 22328c460498c028888c533ab442be12b6d4b669b965James Dong } 22338c460498c028888c533ab442be12b6d4b669b965James Dong 2234c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 2235c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 2236c059860c73678a202bfa33062723e8f82fb779d9James Dong 2237a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2238a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2239c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 224079761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2241be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2242be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2243be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2244be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2245965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2246be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2247be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2249be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2250be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 22518644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2252be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 22533856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld", 2254a472613aec322e25891abf5c77bf3f7e3c244920James Dong mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs); 22558644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2256c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 22578644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 225820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2259d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 2260c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 2261d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2262d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 226393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 226493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 226593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 226693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2267faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 226893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 226943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2270c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 227158ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 2272c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count = (mOwner->use32BitFileOffset() 2274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 2275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 2276c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2277c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (count == 0) { 22781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 227958ae9c530247668f8af36e30d228c716c226b3d4James Dong } 228058ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 228158ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 228258ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 228358ae9c530247668f8af36e30d228c716c226b3d4James Dong } 228413aec890216948b0c364f8f92792129d0335f506James Dong 228513aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 228613aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 22871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 22881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 228913aec890216948b0c364f8f92792129d0335f506James Dong } else { 229013aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 229113aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 229213aec890216948b0c364f8f92792129d0335f506James Dong } else { 229343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 229443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 229543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 229643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 229743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 229813aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 229913aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 2300c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 2301c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 2302c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 230313aec890216948b0c364f8f92792129d0335f506James Dong } 23041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 230513aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 230613aec890216948b0c364f8f92792129d0335f506James Dong } 230713aec890216948b0c364f8f92792129d0335f506James Dong } 230813aec890216948b0c364f8f92792129d0335f506James Dong } 230913aec890216948b0c364f8f92792129d0335f506James Dong 231020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 231125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 231245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 2313690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2314f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 231545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2316bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2317be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 231813aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 231943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2320c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(1, mStszTableEntries->count()); 232158ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 23221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 23231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 232413aec890216948b0c364f8f92792129d0335f506James Dong } 232513aec890216948b0c364f8f92792129d0335f506James Dong 2326be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2327be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2328be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2329c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 1) { 23308f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 233179761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2332be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2333be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2334be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2335a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2336c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() <= 2) { 233779761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2338a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 233979761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2340a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2341a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 234279761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2343a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2344a472613aec322e25891abf5c77bf3f7e3c244920James Dong 234543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // The last ctts box may not have been written yet, and this 234643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // is to make sure that we write out the last ctts box. 234743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 234843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (cttsSampleCount > 0) { 234943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 235043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 235143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 235243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 2353c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 235425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 235543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 235643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 235743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2358df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 2359c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong count, nZeroLengthFrames, mStszTableEntries->count(), mIsAudio? "audio": "video"); 2360872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2361df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs()); 2362872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2363365a963142093a1cd8efdcea76b5f65096a5b115James Dong 236437187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 236537187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 236637187916a486504acaf83bea30147eb5fbf46ae5James Dong } 236737187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2368365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2369365a963142093a1cd8efdcea76b5f65096a5b115James Dong 237045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 2371c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { // no samples written 237229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 237345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 237445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 237545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2376c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (!mIsAudio && mStssTableEntries->count() == 0) { // no sync frames for video 237729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 237845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 237945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 238045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 238145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 238245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 238345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 238445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 238545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 238645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 238745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 238843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 238907ec01904613a0bac32caaa8444b4690998faed7James Dong 239007ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 239107ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 239207ec01904613a0bac32caaa8444b4690998faed7James Dong return; 239307ec01904613a0bac32caaa8444b4690998faed7James Dong } 239407ec01904613a0bac32caaa8444b4690998faed7James Dong 239543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 239643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 239743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 239843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 239943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mIsAudio? 0: 1); 240043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 240143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 240243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 240343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 240443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 240543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 240643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2407c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 240843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 240986b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 241086b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 241186b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 241286b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 241386b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 241486b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 241586b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 241686b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 241786b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 241886b7f47aa7482424cf8fd248f1315311919be3b0James Dong 241986b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 242070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 242170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 242286b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 242370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 242407ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 242507ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 242607ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 242707ec01904613a0bac32caaa8444b4690998faed7James Dong 242843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 242943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 243043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 243143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 243270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 243370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 243470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 243570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 243670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 243770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 243870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 243970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 244043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 244143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 244243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2443faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 24443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("trackProgressStatus: %lld us", timeUs); 2445c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2446215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 2447215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 24483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Fire time tracking progress status at %lld us", timeUs); 2449bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 245093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 245193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 245293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 245393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2454faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 2455bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 2456faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 2457bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 2458faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2459faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 2460faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 2461faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 2462bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2463bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2464faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2465faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 2466faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2467faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2468faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 2469faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 2470bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2471bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2472faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2473faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 2474faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 2475bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2476bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2477faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 2478faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2479faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 2480faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2481d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 24823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setDriftTimeUs: %lld us", driftTimeUs); 2483e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2484d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 2485e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2486e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2487e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 24883856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 2489e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2490e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 2491e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2492e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2493b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 2494b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 2495b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 2496b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 24971c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 24983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 24991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 25001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 25011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 250213aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 250320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 250420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 25053b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 2506c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 250720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 250820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2509d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2510d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 2511d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 2512d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2513690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 2514690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 2515690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2516690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2517690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2518690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2519690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2520690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 252129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 2522690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2523690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2524690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2525690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2526690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 252729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 2528690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2529690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2530690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2531690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2532690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2533690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 253520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 25363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s track time scale: %d", 25371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 25388f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 2539efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 2540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 2541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 2542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 2543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 2544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 2545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 2546b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 2548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 2550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 2552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 2553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 2554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 2555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 2556b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2558b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 2560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 2561b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 2563b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2564b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 2565b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 2567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 2569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 2570965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong writeCttsBox(); 2571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mIsAudio) { 2572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 2573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 2575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 2576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 2577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 2578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 2581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mp4v"); 2586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("s263"); 2588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avc1"); 2590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 259129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 2598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 2606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 2610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 2611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 2612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 2613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 2615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(" ", 32); 2616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 2617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 2618b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 261943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(23 + mCodecSpecificDataSize, 128); 2620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 2623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2624b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 2625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 2627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 2630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 2631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 2634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *fourcc = NULL; 2638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "samr"; 2640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "sawb"; 2642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "mp4a"; 2644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 264529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2661b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 2666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 2668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 2671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 2676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 267843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 268143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(mCodecSpecificDataSize + 23, 128); 2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // max bit rate 2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // avg bit rate 2698b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 2714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 271543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 0x77, 0x00, 2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00, 2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00 2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2752efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2759219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 27618f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 277420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 2812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 2817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2821efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 2829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // language code 2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 2844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 2846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 2847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 2848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 2852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 2853b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 2854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 2857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 2860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 2861b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2862b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 2863b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 2864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 2865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 2868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 2869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 2870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 2871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2872b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 2874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 287543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mCodecSpecificDataSize, 5); 2876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 2878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 2879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 2880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 2881b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 2882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 2884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 2887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 2888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 2889b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2890b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 2891b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 2892b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 2893b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2894b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2895b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 2896b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 2897b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 2901b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2903000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 2904a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 290743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 2908b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2909b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2910000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 2911000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 2912000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2913000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 2914000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 2915000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 2916c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 2917c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mSttsTableEntries->get(duration, 1)); 2918c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back to host byte order 2919c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 2920c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 292320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2924965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 2925965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { // ctts is not for audio 2926965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 2927965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2928965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2929000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 2930000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 2931000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 2932000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2933000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2934965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 2935c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 2936965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 2937965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2938965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2939c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ALOGV("ctts box has %d entries with range [%lld, %lld]", 2940c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 2941965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2942965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 2943000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 2944c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 2945c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCttsTableEntries->get(duration, 1)); 2946c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back host byte order 2947c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1); 2948c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 2949965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 2950965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 2951965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2952b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 2953b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 2954b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2955c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 2956b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 2957b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 295825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 2959b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 2960b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 2961b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2962c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 2963c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 2964b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 2965b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 296620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2967b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 2968b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 2969b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2970c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 2971b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 2972b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 297320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2974b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 2975b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 2976b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2977c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 2978c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 2979c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 2980c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 2981b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2982b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 298320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 298420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 298507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 298607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 298707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 298807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 298907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 299007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 299107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 299207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 299307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 299407b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 299507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 299607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 299707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 299807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 299907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 3000432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 3001432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 300207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 300307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 300407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 300507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 300607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 300707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 300807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 300907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 301020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3011