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 57877e8ae9967a078770416619e99ddb5b010def312James Dong * to make the file streamable. 57977e8ae9967a078770416619e99ddb5b010def312James Dong */ 58077e8ae9967a078770416619e99ddb5b010def312James Dong mStreamableFile = 58177e8ae9967a078770416619e99ddb5b010def312James Dong (mMaxFileSizeLimitBytes != 0 && 58277e8ae9967a078770416619e99ddb5b010def312James Dong mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); 58377e8ae9967a078770416619e99ddb5b010def312James Dong 58477e8ae9967a078770416619e99ddb5b010def312James Dong mWriteMoovBoxToMemory = mStreamableFile; 5857837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 5867837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 5877837c17063a4c50bc856ba59418516fdab731de7James Dong 588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5907837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5927837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 5932dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 5942dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 5952dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 5962dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5972dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 5987837c17063a4c50bc856ba59418516fdab731de7James Dong } 59943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mEstimatedMoovBoxSize, 8); 60077e8ae9967a078770416619e99ddb5b010def312James Dong if (mStreamableFile) { 60177e8ae9967a078770416619e99ddb5b010def312James Dong // Reserve a 'free' box only for streamable file 60277e8ae9967a078770416619e99ddb5b010def312James Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 60377e8ae9967a078770416619e99ddb5b010def312James Dong writeInt32(mEstimatedMoovBoxSize); 60477e8ae9967a078770416619e99ddb5b010def312James Dong write("free", 4); 60577e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 60677e8ae9967a078770416619e99ddb5b010def312James Dong } else { 60777e8ae9967a078770416619e99ddb5b010def312James Dong mMdatOffset = mOffset; 60877e8ae9967a078770416619e99ddb5b010def312James Dong } 6097837c17063a4c50bc856ba59418516fdab731de7James Dong 6107837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 611c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 6121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 6131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 6141acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 6151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 6161acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 6171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 6191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 6201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 6211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 6221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 624a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 625a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 6271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 628a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 62925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 6331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 6341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 6351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 63637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 637674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 63837187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 639a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 640a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 64137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 642a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 643a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 64437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 64537187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 64637187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 64737187916a486504acaf83bea30147eb5fbf46ae5James Dong } 648a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 64937187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 650a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 651a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 6521c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 653b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping writer thread"); 654411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 655411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 656411ba422e3635d534928ffd81abf54f4f291c739James Dong } 6571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 6591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 6601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 6621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 6631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 6641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 6651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 6661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 667411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 668b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Writer thread stopped"); 6691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 6701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 67113f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 67213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 67313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 67413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 67513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 67613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 67713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 67813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 67913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 68013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 68113f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 68213f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 6833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeCompositionMatrix"); 68413f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 68513f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 68613f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 68713f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 68813f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 68913f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 69013f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 69113f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 69213f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 69313f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 69413f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 69513f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 69613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 69713f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 69813f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 69913f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 70013f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 70113f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 70213f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 70313f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 70413f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 70513f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 70613f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 70713f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 70813f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 70913f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 71013f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 71113f6284305e4b27395a23db7882d670bdb1bcae1James Dong 71213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 71313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 71413f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 71513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 71613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 71713f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 71813f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 71913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 72013f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 72113f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 72213f6284305e4b27395a23db7882d670bdb1bcae1James Dong 723411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 724411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 725411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 726411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 727411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 728411ba422e3635d534928ffd81abf54f4f291c739James Dong} 72913f6284305e4b27395a23db7882d670bdb1bcae1James Dong 7308bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG4Writer::reset() { 731674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 73237187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 733411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 734411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 735411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 736411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 737411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 738411ba422e3635d534928ffd81abf54f4f291c739James Dong } 739411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 740411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 741411ba422e3635d534928ffd81abf54f4f291c739James Dong } 74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 7458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 74665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 74937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 75037187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 75137187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 75237187916a486504acaf83bea30147eb5fbf46ae5James Dong } 75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 7558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 7568f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 75865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 75965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 76065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 76165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 76265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 76365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 764b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Duration from tracks range is [%lld, %lld] us", 76565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 7697837c17063a4c50bc856ba59418516fdab731de7James Dong 77037187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 77137187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 772411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 77337187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 77437187916a486504acaf83bea30147eb5fbf46ae5James Dong } 77537187916a486504acaf83bea30147eb5fbf46ae5James Dong 77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 7771acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 778c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 7791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 780c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 7811acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 782c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 7831acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int64_t size = mOffset - mMdatOffset; 7841acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 785c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 7861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 787c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 789c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong const off64_t moovOffset = mOffset; 79077e8ae9967a078770416619e99ddb5b010def312James Dong mWriteMoovBoxToMemory = mStreamableFile; 7917837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 7927837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 7937837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7967837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 7977837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 79843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); 7997837c17063a4c50bc856ba59418516fdab731de7James Dong 8007837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 801c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 8027837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 803674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 8047837c17063a4c50bc856ba59418516fdab731de7James Dong 8057837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 806c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 8077837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 8087837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 8097837c17063a4c50bc856ba59418516fdab731de7James Dong 8107837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 8117837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 8127837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 8137837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 8142dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 815df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("The mp4 file will not be streamable."); 8167837c17063a4c50bc856ba59418516fdab731de7James Dong } 8177837c17063a4c50bc856ba59418516fdab731de7James Dong 8180c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 820411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 82137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 824efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonuint32_t MPEG4Writer::getMpeg4Time() { 825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 826efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // MP4 file uses time counting seconds since midnight, Jan. 1, 1904 827efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // while time function returns Unix epoch values which starts 828efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson // at 1970-01-01. Lets add the number of seconds between them 829efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t mpeg4Time = now + (66 * 365 + 17) * (24 * 60 * 60); 830efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson return mpeg4Time; 831efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson} 832efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson 833efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 834efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 849b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 850b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 853b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 856b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 857b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 858b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 859b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 860b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 86107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 86207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 86307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 864b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 865b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 866b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 869b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 870b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 871b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 8722cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 873b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 874b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 875b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 876b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 877b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 878b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 879b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 880b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 881b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 882b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 883b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); 884b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 885b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 886b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 887b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 888b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 88907ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 89007ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 89107ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 89207ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 89307ec01904613a0bac32caaa8444b4690998faed7James Dong 89407ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 89507ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 89607ec01904613a0bac32caaa8444b4690998faed7James Dong char value[PROPERTY_VALUE_MAX]; 89707ec01904613a0bac32caaa8444b4690998faed7James Dong if (property_get("rw.media.record.test", value, NULL) && 89807ec01904613a0bac32caaa8444b4690998faed7James Dong (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 89907ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 90007ec01904613a0bac32caaa8444b4690998faed7James Dong } 90107ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 90207ec01904613a0bac32caaa8444b4690998faed7James Dong} 90307ec01904613a0bac32caaa8444b4690998faed7James Dong 90470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 90507ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 90607ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 90707ec01904613a0bac32caaa8444b4690998faed7James Dong return; 90807ec01904613a0bac32caaa8444b4690998faed7James Dong } 90907ec01904613a0bac32caaa8444b4690998faed7James Dong 91070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 91170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 91270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 91370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 91470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 91570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 91670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 91770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 91870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 91913aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 92013aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 92113aec890216948b0c364f8f92792129d0335f506James Dong return OK; 92213aec890216948b0c364f8f92792129d0335f506James Dong} 92313aec890216948b0c364f8f92792129d0335f506James Dong 92413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 92513aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 92613aec890216948b0c364f8f92792129d0335f506James Dong} 92713aec890216948b0c364f8f92792129d0335f506James Dong 92813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 92913aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 93013aec890216948b0c364f8f92792129d0335f506James Dong} 93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 932c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 933c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 935c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 936c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 937c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 93820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 93920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 94120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 94403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 94503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 94603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 94703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 94803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 94903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 95003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 95103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 95203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 95303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 95403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 95503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 95603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 95703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 958c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 959c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 96030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 96130ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 96203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 963b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 964b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 965c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 966b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 967c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 968b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 969c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 970b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 971c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 972c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 973c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 974c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 975c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 976b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 977b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 978b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 97943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(length, 65536); 98030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 981b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 982c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 983b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 984c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 985c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 986b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 987b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 98830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 98930ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 99030ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 99130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 9927837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 993674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 9947837c17063a4c50bc856ba59418516fdab731de7James Dong 9957837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 9967837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 997674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong // This happens only when we write the moov box at the end of 998674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong // recording, not for each output video/audio frame we receive. 999c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 10001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 1001c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 10027837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 10037837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 10047837c17063a4c50bc856ba59418516fdab731de7James Dong } 1005674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 1006674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 1007674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 10087837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 10097837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 10107837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 10117837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 10127837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 10137837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = false; 10147837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 10157837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 10167837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 10177837c17063a4c50bc856ba59418516fdab731de7James Dong } 10187837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1019674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 10207837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 10217837c17063a4c50bc856ba59418516fdab731de7James Dong } 10227837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 10237837c17063a4c50bc856ba59418516fdab731de7James Dong} 10247837c17063a4c50bc856ba59418516fdab731de7James Dong 102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 10260c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 102720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10287837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 10297837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 103320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 103420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 103520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 10360c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 103720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1038c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 103920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 104020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10417837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 10427837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 10437837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 10447837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 1045c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 10467837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 10477837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 1048c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 10497837c17063a4c50bc856ba59418516fdab731de7James Dong } 105020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 105120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 105220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 1053674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 105420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 105720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 1058674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 105920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 106020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 1063674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 106420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 106620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 106720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 1068674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 106920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 107020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 107120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 107220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 1073674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 107420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 107520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 107620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 10770c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 1078674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 107920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 108020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 108107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 108207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 108307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 108407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 108507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 108607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 108707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 108807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 108907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 109007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 109107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 109207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 109307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 109407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 109507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 109607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 109707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 109807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 109907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 110007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 110107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 110207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 110307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 110407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 110507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 110607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 110707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 110807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 110907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 111007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 111107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 111207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 111307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 111407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 111507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 111607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 111707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 111807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 111907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 112007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 112107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 112207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 112307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 112407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 112507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 112607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 112707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 112807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 112907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 113007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 113107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 113207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 113307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 113407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 113507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 113607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 113707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 113807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 113907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 114007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 114107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 114207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 114307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 114407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 114507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 114607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 114707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 114807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 114907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 115007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 115107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 115220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1153674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 115520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115678a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 115778a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 115878a1a286f736888ae7af8860b2c424af0d978848James Dong} 115978a1a286f736888ae7af8860b2c424af0d978848James Dong 1160d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1161d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1162d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1163d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1164d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1165d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1166956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1167d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1168d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1169d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1170d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 11711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 117277e8ae9967a078770416619e99ddb5b010def312James Dong if (!mStreamableFile) { 117377e8ae9967a078770416619e99ddb5b010def312James Dong // Add 1024 bytes as error tolerance 117477e8ae9967a078770416619e99ddb5b010def312James Dong return nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes; 117577e8ae9967a078770416619e99ddb5b010def312James Dong } 1176acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1177acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1178acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1179acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1180d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1181d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1182d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1183d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1184d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1185d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1186d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1187d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1188d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1189d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1190d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1191d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1192d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1193d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1194d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1195d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1196d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 119725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 119825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 119925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 120025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 120125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 120225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 120325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 120425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 120525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 120625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 120725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 120825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 120925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1210f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1211df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("setStartTimestampUs: %lld", timeUs); 121243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timeUs, 0ll); 12133c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1214065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1215f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1216df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Earliest track starting time: %lld", mStartTimestampUs); 12173c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 12183c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 12193c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1220f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 12213c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 12223c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 12233c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 12243c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 122558ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 122658ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 122758ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 122858ae9c530247668f8af36e30d228c716c226b3d4James Dong} 122958ae9c530247668f8af36e30d228c716c226b3d4James Dong 123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1233bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 123525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1238a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1239a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1240eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1241bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1242c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1243956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1244be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 1245c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries(new ListTableEntries<off64_t>(1000, 1)), 1248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries(new ListTableEntries<uint32_t>(1000, 3)), 1249c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries(new ListTableEntries<uint32_t>(1000, 1)), 1250c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 1251c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries(new ListTableEntries<uint32_t>(1000, 2)), 125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 125325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1254548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 125513f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 125613f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 125719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 12588f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 12591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 12601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 12611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 12621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 12631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 12641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 12651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1266c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1267c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1268c059860c73678a202bfa33062723e8f82fb779d9James Dong 12691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 12701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1271c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t stcoBoxCount = (mOwner->use32BitFileOffset() 1272c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 1273c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 1274c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stcoBoxSizeBytes = stcoBoxCount * 4; 1275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4); 12761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 127778a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 127878a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 127978a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 128078a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 1281c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 + // stsc box size 1282c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->count() * 4 + // stss box size 1283c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->count() * 8 + // stts box size 1284c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count() * 8 + // ctts box size 128578a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 128678a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 128778a1a286f736888ae7af8860b2c424af0d978848James Dong } 12881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 12891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 12901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 12911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 12921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1293c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(chunkId)); 1294c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(sampleId)); 1295c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->add(htonl(1)); 12961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 12971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 12981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 1299c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->add(htonl(sampleId)); 13001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 13011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 13021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 130379761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 13041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 13055a217fba010e801c255503602bda4b86ac5a6ac9James Dong if (duration == 0) { 13065ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("0-duration samples found: %d", sampleCount); 13075a217fba010e801c255503602bda4b86ac5a6ac9James Dong } 1308c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(sampleCount)); 1309c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->add(htonl(duration)); 13101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 13111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1312965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1313965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1314965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1315965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { 1316965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1317965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1318c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(sampleCount)); 1319c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->add(htonl(duration)); 1320965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1321965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1322c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 1323c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mOwner->use32BitFileOffset()) { 1324c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t value = offset; 1325c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->add(htonl(value)); 1326c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 1327c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->add(hton64(offset)); 1328c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } 13291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 13301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1331c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 13323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setTimeScale"); 1333c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1334c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1335c059860c73678a202bfa33062723e8f82fb779d9James Dong 1336c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1337c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1338c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1339c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1340c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1341c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1342c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1343c059860c73678a202bfa33062723e8f82fb779d9James Dong 1344c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1345c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1346c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1347c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1348c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1349c059860c73678a202bfa33062723e8f82fb779d9James Dong 135043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mTimeScale, 0); 135119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 135219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 135319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 135419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 135519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 135619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 135719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 135819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 135919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 136019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 136119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 136219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 136319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 136419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 136519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 136619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 136719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 136819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 136919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 137019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 137119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 137219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 137319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 137419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 137519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 137619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 137719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 137819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 137919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 138019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 138119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 138420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 138620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1387c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStszTableEntries; 1388c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStcoTableEntries; 1389c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCo64TableEntries; 1390c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStscTableEntries; 1391c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mSttsTableEntries; 1392c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mStssTableEntries; 1393c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong delete mCttsTableEntries; 1394c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 1395c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries = NULL; 1396c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries = NULL; 1397c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries = NULL; 1398c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries = NULL; 1399c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries = NULL; 1400c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries = NULL; 1401c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries = NULL; 1402c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 140320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 140420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 140993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 14103856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initTrackingProgressStatus"); 141193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 141293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 141393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 141493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 141593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 141693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 14173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Receive request to track progress status for every %lld us", timeUs); 141893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 141993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 142093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 142193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 142293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 142393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 14241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 14251c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 14263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ThreadWrapper: %p", me); 14271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 14281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 14291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 14301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 14311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14321c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 14333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk: %p", chunk.mTrack); 14341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 14351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 14361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 14381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 14391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 14411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 14421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 14431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 14441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 14451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 14461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 144743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK(!"Received a chunk for a unknown track"); 14481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 14491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1450fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 14513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeChunkToFile: %lld from %s track", 14525410afcbb0af5d29d9f710a1c2978c500f9792dcPannag Sanketi chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video"); 1453fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1454fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1455fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1456fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1457fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1458fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong off64_t offset = chunk->mTrack->isAvc() 1459fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong ? addLengthPrefixedSample_l(*it) 1460fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1461fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1462fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1463fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1464fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 14651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 14661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 14681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1469fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 14701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1471fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 14721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 14731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1474fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 14753856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("writeAllChunks"); 14761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 147770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 147870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1479e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 148070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 14811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 148270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 148370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 148470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 14851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 1486b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%d chunks are written in the last batch", outstandingChunks); 14871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 14881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1489fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 14903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findChunkToWrite"); 14911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 14931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 14941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 14951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 14961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 14971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 14981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 14991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 15001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 15011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 15063856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Nothing to be written after all"); 1507fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 15081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 15111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 15121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1513fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 15141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 15151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 15161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1517fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1518fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1519fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 152070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 152170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 152270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 152370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 152470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 152570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 152670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1527fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 15281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1530fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1531fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 15321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15341c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 15353856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("threadFunc"); 15361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1537a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1538fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1539fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 15401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1541fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1542fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1543fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1544fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 15451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 15461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1548fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong // Actual write without holding the lock in order to 1549fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong // reduce the blocking time for media track threads. 1550fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 1551fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong mLock.unlock(); 1552fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 1553fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong mLock.lock(); 1554fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 15551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1556fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1557fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 15581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15601c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 15613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startWriterThread"); 15621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 15641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1565e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 15661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 15671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 15681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 15691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 157070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 157170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 15721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 15731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 15741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 15761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 15771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 15781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 15791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 1580411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 15811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 15821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 15831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 158593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1586a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1587a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1588a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1589a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1590a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 159125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 159293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 159319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 159419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 159519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 159670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 159719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 159813f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 159913f6284305e4b27395a23db7882d670bdb1bcae1James Dong if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 160013f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 160113f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 160213f6284305e4b27395a23db7882d670bdb1bcae1James Dong 16035b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong mIsRealTimeRecording = true; 1604e259531ce59ab1f31de5a23124b22536f6a5a767James Dong { 1605e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int32_t isNotRealTime; 1606e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) { 1607e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mIsRealTimeRecording = (isNotRealTime == 0); 1608e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1609e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1610e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 161193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 161293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1613f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1614a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (mIsRealTimeRecording && mOwner->numTracks() > 1) { 1615a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 1616a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 1617a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 1618a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 1619a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 1620a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 162186b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 162286b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 1623a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 162486b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 162586b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 162686b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 162786b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 162886b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 1629df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Start time offset: %lld us", startTimeOffsetUs); 1630a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 1631a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1632f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1633a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1634f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 163525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 163625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 163725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 163825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 163920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 164020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 164120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 164220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 164320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 164420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1645eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 1646c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 164725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1648956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 16491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 165043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 165120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 165225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 165320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 165425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 165525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 165620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 165720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 165837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1659a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 166037187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1661a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1662a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 166337187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 1664b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping %s track", mIsAudio? "Audio": "Video"); 1665eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 166629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Stop() called but track is not started"); 1667eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 1668eaae38445a340c4857c1c5569475879a728e63b7James Dong } 1669eaae38445a340c4857c1c5569475879a728e63b7James Dong 167020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 167137187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 167220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 167320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 167420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 167520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 167620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 167720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 167837187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = (status_t) dummy; 167937187916a486504acaf83bea30147eb5fbf46ae5James Dong 1680b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video"); 168137187916a486504acaf83bea30147eb5fbf46ae5James Dong { 168237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = mSource->stop(); 168337187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK && status != ERROR_END_OF_STREAM) { 168437187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 168537187916a486504acaf83bea30147eb5fbf46ae5James Dong } 168637187916a486504acaf83bea30147eb5fbf46ae5James Dong } 168737187916a486504acaf83bea30147eb5fbf46ae5James Dong 1688b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("%s track stopped", mIsAudio? "Audio": "Video"); 168937187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 169020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 169120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 169225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 169325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 169425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 169525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 169620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 169720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 169820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 169920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 170037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 170137187916a486504acaf83bea30147eb5fbf46ae5James Dong return (void *) err; 170220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 170320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 17053856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getNalUnitType: %d", byte); 17063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 17083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 17093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 17103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 17123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 17133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("findNextStartCode: %p %d", data, length); 17153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 17173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 17183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 17193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 17203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 17223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 17233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 17253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 17263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 17283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 17293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseParamSet"); 17313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 17323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 17333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 17353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 17363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 173729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Param set is malformed, since its length is 0"); 17383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 17393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 17423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 17433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 174429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Seq parameter set malformed"); 17453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 17463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 17483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 17493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 17503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 17513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 17523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 17533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 17543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 175529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Inconsistent profile/level found in seq parameter sets"); 17563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 17573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 17603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 17613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 17623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 17643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 17653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 17673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 17683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copyAVCCodecSpecificData"); 17693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 17713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 17723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 177329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Codec specific data length too short: %d", size); 17743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 17753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 17783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 17793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 17803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 17813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 17823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 17843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 17853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("parseAVCCodecSpecificData"); 17873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 17883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 17893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 17903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 17913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 17923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 17933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 17943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 17953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 17963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 17973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 17983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 17993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 18003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 18013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 180229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 18033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 18063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 18073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 18093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 18103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 181129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("SPS must come before PPS"); 18123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 18153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 18163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 18183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 181929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Only SPS and PPS Nal units are expected"); 18203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 18243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 18283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 18293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 18303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 18313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 18343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 18353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 18363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 183729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find sequence parameter set"); 18383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 184229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 18433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 18483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 18493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 18503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 185129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cound not find picture parameter set"); 18523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 185529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Too many pic parameter sets (%d) found", nPicParamSets); 18563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 18573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18591374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// FIXME: 18601374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above 18611374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket// and remove #if 0 18621374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#if 0 18633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 18643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 18653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 18663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 18673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 186829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 18693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 18703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 18721374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket#endif 18733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 18743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 1875548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 187603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 187703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 1878548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 187903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 188029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Already have codec specific data"); 188103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 188203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 188303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 18843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 188529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Codec specific data length too short: %d", size); 188603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 188703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 188803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 18893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 18903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 18913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 189203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 189303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 18943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 189503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 189603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 189703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 18983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 18993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 190003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 190103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 19023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 19033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 19043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 19053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 190603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 1908b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 1909b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 1910b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 1911b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 1912b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 191303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 19153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 19163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 19173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 19183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 19193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 19203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 19213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 19223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 19233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 19243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 19263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 19273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 19283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 19293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 19313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 19323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 19333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 19343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 19353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 19363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 19373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 19383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 19393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 19403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 19413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 19423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 19433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 19443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 194503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 194603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 194703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 194803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1949872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 1950872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 1951872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 1952872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 1953872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 1954872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 1955872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 1956872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 1957872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 1958872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 1959872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 1960872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 1961872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 1962872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 1963872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1964872a481558350634a3fd5cb67939de288af00ecbJames Dong} 1965872a481558350634a3fd5cb67939de288af00ecbJames Dong 196637187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 196730ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 196813aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 196943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 197013aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 197113aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 197213aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 1973965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 1974965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 1975965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 1976965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 1977965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 1978000e18370baae60ffd9f25b509501dd8c26deabfJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 1979a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 1980965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 1981000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t cttsOffsetTimeUs = 0; 1982000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks 1983000e18370baae60ffd9f25b509501dd8c26deabfJames Dong int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks 198443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry 1985c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t lastSamplesPerChunk = 0; 1986e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1987a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 1988a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 1989a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } else { 1990a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 1991a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 199286106f8b0641444c97a39e9788eeef55ab2a2ac6Glenn Kasten androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 1993985f838934510983d8a887461e98dca60a6e858fJames Dong 1994d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 199520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 199693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 199720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 199893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 199920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 200020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 200120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 200213aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 200320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 200420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 200520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2006a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 2007a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 2008a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 2009a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 2010a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 2011a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 2012a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 2013a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2014a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 201530ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 201630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 201703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 201803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 201903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 2020548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 2021548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 20221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 202303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 202403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 202503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 202603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 202743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_EQ((status_t)OK, err); 20281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 202903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 203003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 203103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 203203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 203303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 203403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 203530ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 203630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 203730ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 203830ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 203930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2040548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 204130ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 2042a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2043a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2044d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 2045d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 2046d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 2047d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 2048d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 2049d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 2050d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 2051d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 2052d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 2053d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 20541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 2055e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 2056b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 2057b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mIsAvc) { 2058b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 2059b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 2060b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 2061b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 2062b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2063b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 2064050b28a593350047845a45a14cc5026221ac1620James Dong 2065d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 20661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 20671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 20681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 2069d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 2070d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 2071d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2072d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2073d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 2074d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 2075d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 2076d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 2077d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2078050b28a593350047845a45a14cc5026221ac1620James Dong 2079d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 2080d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 2081d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 2082d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 2083d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 2084c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 208570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 2086f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 2087f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 20888428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 20893c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 209048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 2091a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 20928428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 209343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(durExcludingEarlierPausesUs, 0ll); 20948428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 209543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(pausedDurationUs, lastDurationUs); 20968428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 2097a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 2098a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 2099a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2100a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 210143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timestampUs, 0ll); 2102000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (!mIsAudio) { 2103965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 2104965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 2105965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 2106000e18370baae60ffd9f25b509501dd8c26deabfJames Dong * Composition time offset = composition time - decoding time 2107965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 2108965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 2109965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 2110965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 2111000e18370baae60ffd9f25b509501dd8c26deabfJames Dong cttsOffsetTimeUs = 2112000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; 211343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(cttsOffsetTimeUs, 0ll); 2114965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 2115000e18370baae60ffd9f25b509501dd8c26deabfJames Dong ALOGV("decoding time: %lld and ctts offset time: %lld", 2116000e18370baae60ffd9f25b509501dd8c26deabfJames Dong timestampUs, cttsOffsetTimeUs); 2117000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2118000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts box table if necessary 2119000e18370baae60ffd9f25b509501dd8c26deabfJames Dong currCttsOffsetTimeTicks = 2120000e18370baae60ffd9f25b509501dd8c26deabfJames Dong (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL; 212143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL); 2122c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 212343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // Force the first ctts table entry to have one single entry 212443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // so that we can do adjustment for the initial track start 212543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // time offset easily in writeCttsBox(). 212643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 212743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(1, currCttsOffsetTimeTicks); 212843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 0; // No sample in ctts box is pending 212943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 213043089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) { 213143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 213243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks; 213343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong cttsSampleCount = 1; // One sample in ctts box is pending 213443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } else { 213543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong ++cttsSampleCount; 213643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 213743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 2138000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2139000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // Update ctts time offset range 2140c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { 2141000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2142000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2143000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else { 2144000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) { 2145000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2146000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) { 2147000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks; 2148000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2149000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2150000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2151965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2152872a481558350634a3fd5cb67939de288af00ecbJames Dong 2153872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsRealTimeRecording) { 2154872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2155872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 2156e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2157e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2158872a481558350634a3fd5cb67939de288af00ecbJames Dong 215943089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(timestampUs, 0ll); 21603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s media time stamp: %lld and previous paused duration %lld", 21618428af5381e835cc783b7ecb0d71cb60961c99c2James Dong mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs); 2162c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2163c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 21643b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 21653b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 21665a217fba010e801c255503602bda4b86ac5a6ac9James Dong // We need to use the time scale based ticks, rather than the 21675a217fba010e801c255503602bda4b86ac5a6ac9James Dong // timestamp itself to determine whether we have to use a new 21685a217fba010e801c255503602bda4b86ac5a6ac9James Dong // stts entry, since we may have rounding errors. 21695a217fba010e801c255503602bda4b86ac5a6ac9James Dong // The calculation is intended to reduce the accumulated 21705a217fba010e801c255503602bda4b86ac5a6ac9James Dong // rounding errors. 21715a217fba010e801c255503602bda4b86ac5a6ac9James Dong currDurationTicks = 21725a217fba010e801c255503602bda4b86ac5a6ac9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 21735a217fba010e801c255503602bda4b86ac5a6ac9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2174c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (currDurationTicks < 0ll) { 2175c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ALOGE("timestampUs %lld < lastTimestampUs %lld for %s track", 2176c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong timestampUs, lastTimestampUs, mIsAudio? "Audio": "Video"); 2177c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong return UNKNOWN_ERROR; 21788c460498c028888c533ab442be12b6d4b669b965James Dong } 21798c460498c028888c533ab442be12b6d4b669b965James Dong 2180c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->add(htonl(sampleSize)); 2181c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() > 2) { 2182c059860c73678a202bfa33062723e8f82fb779d9James Dong 2183a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2184a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2185c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) { 218679761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2187be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2188be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2189be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2190be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2191965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2192be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2193be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2194c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) { 2195be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2196be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 21978644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2198be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 21993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld", 2200a472613aec322e25891abf5c77bf3f7e3c244920James Dong mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs); 22018644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2202c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 22038644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 220420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2205d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 2206c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStssTableEntry(mStszTableEntries->count()); 2207d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2208d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 220993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 221093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 221193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 221293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2213faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 221493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 221543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2216c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 221758ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 2218c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2219c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t count = (mOwner->use32BitFileOffset() 2220c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ? mStcoTableEntries->count() 2221c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong : mCo64TableEntries->count()); 2222c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2223c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (count == 0) { 22241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 222558ae9c530247668f8af36e30d228c716c226b3d4James Dong } 222658ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 222758ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 222858ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 222958ae9c530247668f8af36e30d228c716c226b3d4James Dong } 223013aec890216948b0c364f8f92792129d0335f506James Dong 223113aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 223213aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 22331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 22341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 223513aec890216948b0c364f8f92792129d0335f506James Dong } else { 223613aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 223713aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 223813aec890216948b0c364f8f92792129d0335f506James Dong } else { 223943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 224043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 224143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 224243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 224343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 224413aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 224513aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 2246c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk != mChunkSamples.size()) { 2247c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong lastSamplesPerChunk = mChunkSamples.size(); 2248c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(nChunks, lastSamplesPerChunk); 224913aec890216948b0c364f8f92792129d0335f506James Dong } 22501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 225113aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 225213aec890216948b0c364f8f92792129d0335f506James Dong } 225313aec890216948b0c364f8f92792129d0335f506James Dong } 225413aec890216948b0c364f8f92792129d0335f506James Dong } 225513aec890216948b0c364f8f92792129d0335f506James Dong 225620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 225725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 225845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 2259690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2260f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 226145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2262bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2263be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 226413aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 226543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2266c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong addOneStscTableEntry(1, mStszTableEntries->count()); 226758ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 22681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 22691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 227013aec890216948b0c364f8f92792129d0335f506James Dong } 227113aec890216948b0c364f8f92792129d0335f506James Dong 2272be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2273be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2274be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2275c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 1) { 22768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 227779761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2278be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2279be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2280be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2281a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2282c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() <= 2) { 228379761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2284a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 228579761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2286a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2287a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 228879761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2289a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2290a472613aec322e25891abf5c77bf3f7e3c244920James Dong 229143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // The last ctts box may not have been written yet, and this 229243089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong // is to make sure that we write out the last ctts box. 229343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) { 229443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong if (cttsSampleCount > 0) { 229543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks); 229643089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 229743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong } 229843089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong 2299c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 230025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 230143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 230243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 230343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2304df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 2305c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong count, nZeroLengthFrames, mStszTableEntries->count(), mIsAudio? "audio": "video"); 2306872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2307df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs()); 2308872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2309365a963142093a1cd8efdcea76b5f65096a5b115James Dong 231037187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 231137187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 231237187916a486504acaf83bea30147eb5fbf46ae5James Dong } 231337187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2314365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2315365a963142093a1cd8efdcea76b5f65096a5b115James Dong 231645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 2317c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mStszTableEntries->count() == 0) { // no samples written 231829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("The number of recorded samples is 0"); 231945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 232045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 232145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2322c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (!mIsAudio && mStssTableEntries->count() == 0) { // no sync frames for video 232329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("There are no sync frames for video track"); 232445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 232545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 232645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 232745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 232845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 232945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 233045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 233145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 233245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 233345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 233443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 233507ec01904613a0bac32caaa8444b4690998faed7James Dong 233607ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 233707ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 233807ec01904613a0bac32caaa8444b4690998faed7James Dong return; 233907ec01904613a0bac32caaa8444b4690998faed7James Dong } 234007ec01904613a0bac32caaa8444b4690998faed7James Dong 234143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 234243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 234343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 234443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 234543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mIsAudio? 0: 1); 234643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 234743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 234843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 234943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 235043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 235143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 235243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 2353c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->count()); 235443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 235586b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 235686b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 235786b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 235886b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 235986b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 236086b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 236186b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 236286b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 236386b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 236486b7f47aa7482424cf8fd248f1315311919be3b0James Dong 236586b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 236670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 236770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 236886b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 236970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 237007ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 237107ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 237207ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 237307ec01904613a0bac32caaa8444b4690998faed7James Dong 237443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 237543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 237643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 237743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 237870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 237970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 238070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 238170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 238270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 238370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 238470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 238570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 238643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 238743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 238843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2389faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 23903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("trackProgressStatus: %lld us", timeUs); 2391c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong 2392215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 2393215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 23943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Fire time tracking progress status at %lld us", timeUs); 2395bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 239693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 239793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 239893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 239993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2400faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 2401bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 2402faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 2403bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 2404faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2405faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 2406faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 2407faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 2408bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2409bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2410faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2411faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 2412faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2413faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2414faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 2415faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 2416bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2417bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2418faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2419faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 2420faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 2421bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2422bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2423faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 2424faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2425faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 2426faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2427d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 24283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setDriftTimeUs: %lld us", driftTimeUs); 2429e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2430d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 2431e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2432e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2433e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 24343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 2435e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2436e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 2437e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2438e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2439b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 2440b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 2441b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 2442b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 24431c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 24443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("bufferChunk"); 24451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 24461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 24471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 244813aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 244920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 245020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24513b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 2452c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 245320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 245420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2455d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2456d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 2457d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 2458d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2459690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 2460690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 2461690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2462690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2463690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2464690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2465690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2466690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 246729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Missing codec specific data"); 2468690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2469690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2470690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2471690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2472690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 247329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unexepected codec specific data found"); 2474690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2475690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2476690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2477690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2478690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2479690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 248120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%s track time scale: %d", 24831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 24848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 2485efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlsson uint32_t now = getMpeg4Time(); 2486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 2487b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 2488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 2489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 2490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 2491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 2492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 2494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 2496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 2498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 2499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 2500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 2501b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 2502b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2503b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2504b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 2506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 2507b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 2509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 2511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 2513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 2515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 2516965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong writeCttsBox(); 2517b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mIsAudio) { 2518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 2519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 2521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 2522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 2523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 2524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 2527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mp4v"); 2532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("s263"); 2534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avc1"); 2536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 253729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown mime type '%s'.", mime); 2538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 2544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2546b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 2552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 2556b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 2557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 2558b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 2559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 2561b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(" ", 32); 2562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 2563b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 2564b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 256543089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(23 + mCodecSpecificDataSize, 128); 2566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 2569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 2571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 2573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 2576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 2577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 2580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *fourcc = NULL; 2584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "samr"; 2586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "sawb"; 2588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "mp4a"; 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->beginBox(fourcc); // audio format 2596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 2599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 2602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 2604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 2605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 2609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 2610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 2612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 2614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 2617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2618b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 2622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 262443089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 262743089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_LT(mCodecSpecificDataSize + 23, 128); 2628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 2633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 2634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 2639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 2641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // max bit rate 2643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // avg bit rate 2644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 266143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mCodecSpecificDataSize, 0); 2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 2677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 0x77, 0x00, 2678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00, 2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00 2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2698efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeTkhdBox(uint32_t now) { 2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2705219f195159f93d627af2b243732e3f9020511a46James Dong mOwner->writeInt32(mTrackId); // track id starts with 1 2706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 27078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 2709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 2716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 272020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 2727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 2734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 2737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 2738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 2739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 2740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 2741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2767efcdf187baab9ec29e12adcf85e63fe3e6d5aa4dJohannes Carlssonvoid MPEG4Writer::Track::writeMdhdBox(uint32_t now) { 2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 2776b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // language code 2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 2789b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 2803b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2804b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2805b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 2806b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 2807b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2808b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 2809b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 2810b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 2811b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2812b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2813b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 2814b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 2815b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 2816b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 2817b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2818b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2819b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 2820b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 282143089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GE(mCodecSpecificDataSize, 5); 2822b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2823b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 2824b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 2825b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 2826b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 2827b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 2828b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2829b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 2830b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2831b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2832b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 2833b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 2834b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 2835b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2836b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 2837b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 2838b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 2839b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2840b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2841b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 2842b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 2843b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 2844b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 2845b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 2846b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 2847b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2848b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2849000e18370baae60ffd9f25b509501dd8c26deabfJames Dongint32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const { 2850a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 2851b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2852b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 285343089daaf82bd2b8e5f9a29b80af5abaae4657b3James Dong CHECK_GT(mStartTimestampUs, moovStartTimeUs); 2854b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2855b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2856000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 2857000e18370baae60ffd9f25b509501dd8c26deabfJames Dong} 2858000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2859000e18370baae60ffd9f25b509501dd8c26deabfJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 2860000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->beginBox("stts"); 2861000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 2862c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 2863c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mSttsTableEntries->get(duration, 1)); 2864c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back to host byte order 2865c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1); 2866c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mSttsTableEntries->write(mOwner); 2867b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 2868b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 286920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2870965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 2871965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { // ctts is not for audio 2872965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 2873965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2874965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2875000e18370baae60ffd9f25b509501dd8c26deabfJames Dong // There is no B frame at all 2876000e18370baae60ffd9f25b509501dd8c26deabfJames Dong if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) { 2877000e18370baae60ffd9f25b509501dd8c26deabfJames Dong return; 2878000e18370baae60ffd9f25b509501dd8c26deabfJames Dong } 2879000e18370baae60ffd9f25b509501dd8c26deabfJames Dong 2880965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 2881c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (mCttsTableEntries->count() == 0) { 2882965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 2883965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2884965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2885c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong ALOGV("ctts box has %d entries with range [%lld, %lld]", 2886c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs); 2887965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2888965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 2889000e18370baae60ffd9f25b509501dd8c26deabfJames Dong mOwner->writeInt32(0); // version=0, flags=0 2890c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong uint32_t duration; 2891c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong CHECK(mCttsTableEntries->get(duration, 1)); 2892c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong duration = htonl(duration); // Back host byte order 2893c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime() - mMinCttsOffsetTimeUs), 1); 2894c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCttsTableEntries->write(mOwner); 2895965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 2896965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 2897965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2898b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 2899b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 2900b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2901c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStssTableEntries->write(mOwner); 2902b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 2903b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 290425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 2905b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 2906b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 2907b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2908c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mOwner->writeInt32(0); 2909c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStszTableEntries->write(mOwner); 2910b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 2911b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 291220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2913b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 2914b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 2915b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2916c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStscTableEntries->write(mOwner); 2917b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 2918b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 291920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2920b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 2921b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 2922b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2923c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong if (use32BitOffset) { 2924c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mStcoTableEntries->write(mOwner); 2925c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong } else { 2926c620cbd7f8dc75f6819e2b862d3c09970560bc63James Dong mCo64TableEntries->write(mOwner); 2927b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2928b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 292920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 293020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 293107b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 293207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 293307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 293407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 293507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 293607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 293707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 293807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 293907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 294007b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 294107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 294207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 294307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 294407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 294507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 2946432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 2947432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 294807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 294907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 295007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 295107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 295207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 295307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 295407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 295507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 295620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 2957