MPEG4Writer.cpp revision c5f0c714dc4225cd2ec305d5ddd297964a3dd3dc
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 <ctype.h> 2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h> 2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.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> 35365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h> 3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h" 3819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 4325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track(MPEG4Writer *owner, const sp<MediaSource> &source); 448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void stop(); 49a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong void pause(); 5025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 523b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 53d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong void writeTrackHeader(int32_t trackID, bool use32BitOffset = true); 551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void addChunkOffset(off_t offset) { mChunkOffsets.push_back(offset); } 6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 64693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 66a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 67a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 71c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 72d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t mMaxWriteTimeUs; 748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // mNumSamples is used to track how many samples in mSampleSizes List. 79ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // This is to reduce the cost associated with mSampleSizes.size() call, 80ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // since it is O(n). Ideally, the fix should be in List class. 81ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong size_t mNumSamples; 828644c14618d30d9e57a69df40ed939986ebf02c4James Dong List<size_t> mSampleSizes; 83be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong bool mSamplesHaveSameSize; 84be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 8513aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 8613aec890216948b0c364f8f92792129d0335f506James Dong List<off_t> mChunkOffsets; 8713aec890216948b0c364f8f92792129d0335f506James Dong 8813aec890216948b0c364f8f92792129d0335f506James Dong struct StscTableEntry { 8913aec890216948b0c364f8f92792129d0335f506James Dong 9013aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 9113aec890216948b0c364f8f92792129d0335f506James Dong : firstChunk(chunk), 9213aec890216948b0c364f8f92792129d0335f506James Dong samplesPerChunk(samples), 9313aec890216948b0c364f8f92792129d0335f506James Dong sampleDescriptionId(id) {} 9413aec890216948b0c364f8f92792129d0335f506James Dong 9513aec890216948b0c364f8f92792129d0335f506James Dong uint32_t firstChunk; 9613aec890216948b0c364f8f92792129d0335f506James Dong uint32_t samplesPerChunk; 9713aec890216948b0c364f8f92792129d0335f506James Dong uint32_t sampleDescriptionId; 9813aec890216948b0c364f8f92792129d0335f506James Dong }; 9913aec890216948b0c364f8f92792129d0335f506James Dong List<StscTableEntry> mStscTableEntries; 10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 101050b28a593350047845a45a14cc5026221ac1620James Dong List<int32_t> mStssTableEntries; 102365a963142093a1cd8efdcea76b5f65096a5b115James Dong List<int64_t> mChunkDurations; 103050b28a593350047845a45a14cc5026221ac1620James Dong 104be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong struct SttsTableEntry { 105be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 1068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong SttsTableEntry(uint32_t count, uint32_t durationUs) 1078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong : sampleCount(count), sampleDurationUs(durationUs) {} 108be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 109be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t sampleCount; 1108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong uint32_t sampleDurationUs; 111be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong }; 112be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SttsTableEntry> mSttsTableEntries; 113be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 116548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 11793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 1203c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 12193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 12293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 12325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void threadEntry(); 12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t makeAVCCodecSpecificData( 12803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size); 129215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 130215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 131faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 13293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 13303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 134215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Utilities for collecting statistical data 135215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong void logStatisticalData(bool isAudio); 136215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong void findMinAvgMaxSampleDurationMs( 137215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t *min, int32_t *avg, int32_t *max); 138215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong void findMinMaxChunkDurations(int64_t *min, int64_t *max); 139215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 14019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 14119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR 1 14703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFile(fopen(filename, "wb")), 1501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 151a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 152a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 15413aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1557837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 156f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong mInterleaveDurationUs(1000000) { 1570c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mFile != NULL); 15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16030ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 16130ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mFile(fdopen(fd, "wb")), 1621acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 163a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 164a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 16530ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 16613aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1677837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 168f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong mInterleaveDurationUs(1000000) { 16930ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(mFile != NULL); 17030ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 17130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 17220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1822dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 18325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track *track = new Track(this, source); 18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 1852dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 1862dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 190a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 191a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 19293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 193a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 194a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 195a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 196a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 197a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 198a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 199a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 200a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 201a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 202a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 203a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 204a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 205a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2062dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 2072dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 2082dec2b5be2056c6d9428897dc672185872d30d17James Dong // 2092dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 2102dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 2112dec2b5be2056c6d9428897dc672185872d30d17James Dong // Currently, lets set to 0.4% for now. 2122dec2b5be2056c6d9428897dc672185872d30d17James Dong 2132dec2b5be2056c6d9428897dc672185872d30d17James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB, 2142dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 2152dec2b5be2056c6d9428897dc672185872d30d17James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 4 2162dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 2172dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 2182dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 2192dec2b5be2056c6d9428897dc672185872d30d17James Dong 2202dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 2212dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 2222dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 2232dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024; // 4 KB 2242dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 2252dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 2262dec2b5be2056c6d9428897dc672185872d30d17James Dong 2272dec2b5be2056c6d9428897dc672185872d30d17James Dong if (mMaxFileSizeLimitBytes != 0) { 2282dec2b5be2056c6d9428897dc672185872d30d17James Dong size = mMaxFileSizeLimitBytes * 4 / 1000; 2292dec2b5be2056c6d9428897dc672185872d30d17James Dong } else if (mMaxFileDurationLimitUs != 0) { 2302dec2b5be2056c6d9428897dc672185872d30d17James Dong if (bitRate <= 0) { 2312dec2b5be2056c6d9428897dc672185872d30d17James Dong // We could not estimate the file size since bitRate is not set. 2322dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 2332dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 2342dec2b5be2056c6d9428897dc672185872d30d17James Dong size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000); 2352dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2362dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2372dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 2382dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 2392dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2402dec2b5be2056c6d9428897dc672185872d30d17James Dong 2412dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 2422dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 2432dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 2442dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 2452dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2462dec2b5be2056c6d9428897dc672185872d30d17James Dong 2472dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 2482dec2b5be2056c6d9428897dc672185872d30d17James Dong " moov size %lld bytes", 2492dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 2502dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 2512dec2b5be2056c6d9428897dc672185872d30d17James Dong} 2522dec2b5be2056c6d9428897dc672185872d30d17James Dong 2532dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 25525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2582dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 2592dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 2602dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 2612dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 2622dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 2632dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2642dec2b5be2056c6d9428897dc672185872d30d17James Dong 2652dec2b5be2056c6d9428897dc672185872d30d17James Dong // System property can overwrite the file offset bits parameter 2662dec2b5be2056c6d9428897dc672185872d30d17James Dong char value[PROPERTY_VALUE_MAX]; 2672dec2b5be2056c6d9428897dc672185872d30d17James Dong if (property_get("media.stagefright.record-64bits", value, NULL) 2682dec2b5be2056c6d9428897dc672185872d30d17James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 2692dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 2702dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2712dec2b5be2056c6d9428897dc672185872d30d17James Dong 272065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 27393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 274a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 275a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 276a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 27793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 278a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 279a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 280a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 281a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 2838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 2848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 2858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 2868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 2878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("movie time scale: %d", mTimeScale); 2888f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 2897837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = true; 2907837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 2917837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 2927837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 2937837c17063a4c50bc856ba59418516fdab731de7James Dong 29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("ftyp"); 29593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 29693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t fileType; 29793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (param && param->findInt32(kKeyFileType, &fileType) && 29893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong fileType != OUTPUT_FORMAT_MPEG_4) { 29993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("3gp4"); 30093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } else { 30193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("isom"); 30293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 30393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 30693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("3gp4"); 30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); 30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3097837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3117837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 3122dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 3132dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 3142dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 3152dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3162dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 3177837c17063a4c50bc856ba59418516fdab731de7James Dong } 3187837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mEstimatedMoovBoxSize >= 8); 3197837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 3207837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize); 3217837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 3227837c17063a4c50bc856ba59418516fdab731de7James Dong 3237837c17063a4c50bc856ba59418516fdab731de7James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 3247837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 3257837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 3261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 3271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 3281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 3291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 3301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 3311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 3321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 3331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 3341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 3351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 3361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 3371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 338a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 339a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 3411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 342a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 34325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 346a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::pause() { 347a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mFile == NULL) { 348a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return; 349a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 350a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 351a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 352a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 353a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it)->pause(); 354a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 355a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 356a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 3571c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 3581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("stopWriterThread"); 3591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 3601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 3611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 3621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 3631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 3641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 3651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 3661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 3671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 3681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 3691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 3701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() { 37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->stop(); 38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 3828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 3838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 38420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 3887837c17063a4c50bc856ba59418516fdab731de7James Dong 38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 3901acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 3911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 3921acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 3931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fwrite(&size, 1, 4, mFile); 3941acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 3951acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fseeko(mFile, mMdatOffset + 8, SEEK_SET); 3961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int64_t size = mOffset - mMdatOffset; 3971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 3981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fwrite(&size, 1, 8, mFile); 3991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 4007837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 4037837c17063a4c50bc856ba59418516fdab731de7James Dong const off_t moovOffset = mOffset; 4047837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = true; 4057837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 4067837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 4077837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 4088f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t duration = (maxDurationUs * mTimeScale) / 1E6; 40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("moov"); 41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("mvhd"); 41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // version=0, flags=0 41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // creation time 41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // modification time 4168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong writeInt32(mTimeScale); // mvhd timescale 4171acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(duration); 4181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(0x10000); // rate: 1.0 41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0x100); // volume 42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0); // reserved 42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // matrix 42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); 42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x40000000); 43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mTracks.size() + 1); // nextTrackID 43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // mvhd 44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t id = 1; 44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it, ++id) { 4441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong (*it)->writeTrackHeader(id, mUse32BitOffset); 44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // moov 44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4487837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 4497837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 4507837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 4517837c17063a4c50bc856ba59418516fdab731de7James Dong 4527837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 4537837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 4547837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 4557837c17063a4c50bc856ba59418516fdab731de7James Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); 4567837c17063a4c50bc856ba59418516fdab731de7James Dong 4577837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 4582dec2b5be2056c6d9428897dc672185872d30d17James Dong fseeko(mFile, mOffset, SEEK_SET); 4597837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 4607837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 4617837c17063a4c50bc856ba59418516fdab731de7James Dong 4627837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 4637837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 4647837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 4657837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 4662dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 4672dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("The mp4 file will not be streamable."); 4687837c17063a4c50bc856ba59418516fdab731de7James Dong } 4697837c17063a4c50bc856ba59418516fdab731de7James Dong 4700c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4727837c17063a4c50bc856ba59418516fdab731de7James Dong fflush(mFile); 47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fclose(mFile); 47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFile = NULL; 475a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = false; 47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 47720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 47813aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 47913aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 48013aec890216948b0c364f8f92792129d0335f506James Dong return OK; 48113aec890216948b0c364f8f92792129d0335f506James Dong} 48213aec890216948b0c364f8f92792129d0335f506James Dong 48313aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 48413aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 48513aec890216948b0c364f8f92792129d0335f506James Dong} 48613aec890216948b0c364f8f92792129d0335f506James Dong 48713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 48813aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 48913aec890216948b0c364f8f92792129d0335f506James Dong} 49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 49113aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 49220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t old_offset = mOffset; 49320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 49420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 49520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1, buffer->range_length(), mFile); 49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 49820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 49920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 50020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 50120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 50203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 50303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 50403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 50503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 50603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 50703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 50803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 50903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 51003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 51103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 51203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 51303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 51403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 51503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 51613aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 51730ab66297501757d745b9ae10da61adcd891f497Andreas Huber off_t old_offset = mOffset; 51830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 51930ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 52003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 52103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 52203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t x = length >> 24; 52303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 52403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 16) & 0xff; 52503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 52603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 8) & 0xff; 52703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 52803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = length & 0xff; 52903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 53003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 53130ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(length < 65536); 53230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 53330ab66297501757d745b9ae10da61adcd891f497Andreas Huber uint8_t x = length >> 8; 53430ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 53530ab66297501757d745b9ae10da61adcd891f497Andreas Huber x = length & 0xff; 53630ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 53703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 53830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 53930ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 54030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1, length, mFile); 54130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 54203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 54303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mOffset += length + 4; 54403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 54530ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset += length + 2; 54603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 54730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 54830ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 54930ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 55030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 5517837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 5527837c17063a4c50bc856ba59418516fdab731de7James Dong const void *ptr, size_t size, size_t nmemb, FILE *stream) { 5537837c17063a4c50bc856ba59418516fdab731de7James Dong 5547837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 5557837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 5561acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 5571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 5587837c17063a4c50bc856ba59418516fdab731de7James Dong for (List<off_t>::iterator it = mBoxes.begin(); 5597837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 5607837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 5617837c17063a4c50bc856ba59418516fdab731de7James Dong } 5627837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 5637837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); 5647837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 5657837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 5667837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 5677837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 5687837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 5697837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 5707837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = false; 5717837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 5727837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 5737837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 5747837c17063a4c50bc856ba59418516fdab731de7James Dong } 5757837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 5767837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 5777837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 5787837c17063a4c50bc856ba59418516fdab731de7James Dong } 5797837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 5807837c17063a4c50bc856ba59418516fdab731de7James Dong} 5817837c17063a4c50bc856ba59418516fdab731de7James Dong 58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 5830c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5857837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 5867837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 5930c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset = *--mBoxes.end(); 59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5987837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 5997837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 6007837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 6017837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 6027837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, offset, SEEK_SET); 6037837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 6047837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 6057837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 6067837c17063a4c50bc856ba59418516fdab731de7James Dong } 60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 6107837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 1, mFile); 61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 6157837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 2, mFile); 61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 61820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 6207837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 4, mFile); 62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 6257837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 8, mFile); 62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 6307837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, n + 1, mFile); 63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 6340c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 6357837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, 4, mFile); 63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 6397837c17063a4c50bc856ba59418516fdab731de7James Dong write(data, 1, size, mFile); 64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 642d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 643d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 644d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 645d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 646d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 647d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 648956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 649d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 650d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 651d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 652d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 653d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes); 654d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 655d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 656d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 657d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 658d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 659d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 660d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 661d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 662d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 663d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 664d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 665d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 666d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 667d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 668d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 669d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 670d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 67125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 67225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 67325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 67425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 67525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 67625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 67725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 67825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 67925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 68025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 68125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 68225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 68325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 684f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 685f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("setStartTimestampUs: %lld", timeUs); 686f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong CHECK(timeUs >= 0); 6873c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 688065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 689f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 690f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("Earliest track starting time: %lld", mStartTimestampUs); 6913c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 6923c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 6933c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 694f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 6953c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 6963c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 6973c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 6983c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 69958ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 70058ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 70158ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 70258ae9c530247668f8af36e30d228c716c226b3d4James Dong} 70358ae9c530247668f8af36e30d228c716c226b3d4James Dong 70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 70620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 70725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber MPEG4Writer *owner, const sp<MediaSource> &source) 70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 70925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 712a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 713a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 714c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 715956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 716be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 71825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 719548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 72025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS(false) { 72119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 7228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 7238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!mMeta->findInt32(kKeyTimeScale, &mTimeScale)) { 7248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 7258f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 7261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 7281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 7291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 7301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 7311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 7321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 7331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 7348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 73519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 73619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 73719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 73819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 73919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 74019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 74119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 74219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 74319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 74419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 74519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 74619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 74719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 74819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 74919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 75019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 75119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 75219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 75319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 75419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 75519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 75619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 75719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 75819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 75919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 76019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 76119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 76219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 76319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 76419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 76519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 77893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("initTrackingProgressStatus"); 77993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 78093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 78193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 78293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 78393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 78493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 78593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Receive request to track progress status for every %lld us", timeUs); 78693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 78793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 78893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 78993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 79093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 79193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 7921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 7931c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 7941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("ThreadWrapper: %p", me); 7951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 7961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 7971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 7981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 7991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8001c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 8011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("bufferChunk: %p", chunk.mTrack); 8021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 8031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 8041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 8061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 8071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 8091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 8101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 8111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 8121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK("Received a chunk for a unknown track" == 0); 8161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 8171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8181c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeFirstChunk(ChunkInfo* info) { 8191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("writeFirstChunk: %p", info->mTrack); 8201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = info->mChunks.begin(); 8221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); 8231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != chunkIt->mSamples.end(); ++it) { 8241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong off_t offset = info->mTrack->isAvc() 8261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ? addLengthPrefixedSample_l(*it) 8271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong : addSample_l(*it); 8281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it == chunkIt->mSamples.begin()) { 8291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info->mTrack->addChunkOffset(offset); 8301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Done with the current chunk. 8341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Release all the samples in this chunk. 8351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!chunkIt->mSamples.empty()) { 8361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); 8371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 8381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 8391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong chunkIt->mSamples.erase(it); 8401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong chunkIt->mSamples.clear(); 8421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info->mChunks.erase(chunkIt); 8431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 8441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8451c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeChunks() { 8461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("writeChunks"); 8471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 8481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mChunkInfos.empty()) { 8491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<ChunkInfo>::iterator it = mChunkInfos.begin(); 8501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!it->mChunks.empty()) { 8511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(OK, writeOneChunk()); 8521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ++outstandingChunks; 8531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mTrack = NULL; 8551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.erase(it); 8561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 8581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGD("%d chunks are written in the last batch", outstandingChunks); 8591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 8601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8611c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::writeOneChunk() { 8621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("writeOneChunk"); 8631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Find the smallest timestamp, and write that chunk out 8651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // XXX: What if some track is just too slow? 8661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 8671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 8681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 8691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 8701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 8711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 8741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 8751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 8801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("Nothing to be written after all"); 8811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 8821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 8851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 8861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 8881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 8891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 8901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writeFirstChunk(&(*it)); 8911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 8931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 8941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 8951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8961c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 8971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("threadFunc"); 8981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 8991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 9001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 9011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 9021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 9031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(writeOneChunk(), OK); 9041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 9051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 9061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 9081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Write ALL samples 9091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 9101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writeChunks(); 9111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 9121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 9131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9141c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 9151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("startWriterThread"); 9161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 9181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 9191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 9201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 9211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 9221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 9231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 9241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 9251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 9271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 9281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 9291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 9301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 9311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 9321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 9331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 93493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 935a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 936a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 937a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 938a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 939a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 94025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 94193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 94219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 94319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 94419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 94519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 94693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 94793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 948f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 949f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 950f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 95125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 95225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 95325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 95425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 961c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 96225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 963956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 96420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 96525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 96620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 96725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 96825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 97020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 971a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::Track::pause() { 972a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 973a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 974a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() { 97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource->stop(); 98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 98825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 98925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 99025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 99125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 99220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 99320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 99420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 99620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track->threadEntry(); 99720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 99820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 99920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 100020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1001548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h> 1002548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) { 1003548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber const uint8_t *data = (const uint8_t *)_data; 1004548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t offset = 0; 1005548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber while (offset < size) { 1006548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("0x%04x ", offset); 1007548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1008548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t n = size - offset; 1009548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (n > 16) { 1010548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber n = 16; 1011548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1012548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1013548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < 16; ++i) { 1014548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (i == 8) { 1015548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 1016548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1017548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1018548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (offset + i < size) { 1019548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%02x ", data[offset + i]); 1020548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 1021548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 1022548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1023548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1024548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1025548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 1026548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1027548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < n; ++i) { 1028548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (isprint(data[offset + i])) { 1029548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%c", data[offset + i]); 1030548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 1031548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("."); 1032548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1033548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1034548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1035548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("\n"); 1036548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1037548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber offset += 16; 1038548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1039548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber} 1040548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1041548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 104203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 104303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 1044548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber // hexdump(data, size); 1045548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 104603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 1047548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Already have codec specific data"); 104803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 104903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 105003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 105103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) { 1052548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Must start with a start code"); 105303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 105403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 105503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 105603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamOffset = 4; 105703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber while (picParamOffset + 3 < size 105803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) { 105903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber ++picParamOffset; 106003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 106103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 106203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (picParamOffset + 3 >= size) { 1063548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Could not find start-code for pictureParameterSet"); 106403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 106503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 106603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 106703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t seqParamSetLength = picParamOffset - 4; 106803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamSetLength = size - picParamOffset - 4; 106903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 107003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 107103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2; 107203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 107303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 107403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 107503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 107603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = 0x42; // profile 107703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = 0x80; 107803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[3] = 0x1e; // level 107903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 108003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 108103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 3; // length size == 4 bytes 108203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 108303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 1; // length size == 2 bytes 108403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 108503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 108603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[5] = 0xe0 | 1; 108703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[6] = seqParamSetLength >> 8; 108803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[7] = seqParamSetLength & 0xff; 108903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[8], &data[4], seqParamSetLength); 109003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header += 8 + seqParamSetLength; 109103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 109203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = picParamSetLength >> 8; 109303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = picParamSetLength & 0xff; 109403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength); 109503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 109603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 109703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 109803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 10998644c14618d30d9e57a69df40ed939986ebf02c4James Dongstatic bool collectStatisticalData() { 11008644c14618d30d9e57a69df40ed939986ebf02c4James Dong char value[PROPERTY_VALUE_MAX]; 11018644c14618d30d9e57a69df40ed939986ebf02c4James Dong if (property_get("media.stagefright.record-stats", value, NULL) 11028644c14618d30d9e57a69df40ed939986ebf02c4James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 11038644c14618d30d9e57a69df40ed939986ebf02c4James Dong return true; 11048644c14618d30d9e57a69df40ed939986ebf02c4James Dong } 11058644c14618d30d9e57a69df40ed939986ebf02c4James Dong return false; 11068644c14618d30d9e57a69df40ed939986ebf02c4James Dong} 11078644c14618d30d9e57a69df40ed939986ebf02c4James Dong 110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() { 110930ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 111013aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 111113aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 111213aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 111313aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 11148f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t lastTimestampUs = 0; // Previous sample time stamp in ms 11158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t lastDurationUs = 0; // Between the previous two samples in ms 11168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 1117be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 1118a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 11191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t timestampUs; 1120d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 11218644c14618d30d9e57a69df40ed939986ebf02c4James Dong bool collectStats = collectStatisticalData(); 112220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1123ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mNumSamples = 0; 11241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMaxWriteTimeUs = 0; 112593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 112620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 112793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 112920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 113020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 113113aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 113220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 113420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1135a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 1136a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 1137a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 1138a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 1139a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 1140a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 1141a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 1142a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1143a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 114430ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 114530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 114603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 114703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 114803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 1149548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 1150548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 11511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 115203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 115303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 115403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 115503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 1156be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 11571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 115803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 115903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 116003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 116103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 116203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 116303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 116430ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 116530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 116630ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 116730ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 116830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1169548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 117030ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 1171548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && 11721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong count == 1 && mIsMPEG4 && mCodecSpecificData == NULL) { 117303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI mpeg4 encoder does not properly set the 117403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // codec-specific-data flag. 117530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *data = 117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const size_t size = buffer->range_length(); 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t offset = 0; 118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (offset + 3 < size) { 118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (data[offset] == 0x00 && data[offset + 1] == 0x00 118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) { 118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++offset; 118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11910c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber // CHECK(offset + 3 < size); 1192bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber if (offset + 3 >= size) { 1193bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // XXX assume the entire first chunk of data is the codec specific 1194bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // data. 1195bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber offset = size; 1196bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber } 119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificDataSize = offset; 119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = malloc(offset); 120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber memcpy(mCodecSpecificData, data, offset); 120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->set_range(buffer->range_offset() + offset, size - offset); 120303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 120403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size == offset) { 120503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 120603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 120703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 120803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 120903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 1210548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1211548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 12121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (!mGotAllCodecSpecificData && mIsAvc && count < 3) { 121303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI video encoder does not flag codec specific data 121403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // as such and also splits up SPS and PPS across two buffers. 121503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 121603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data = 121703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 121803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 121903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t size = buffer->range_length(); 122003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 122103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber CHECK(count == 2 || mCodecSpecificData == NULL); 122203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 122303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t offset = mCodecSpecificDataSize; 122403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize += size + 4; 122503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = 122603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber realloc(mCodecSpecificData, mCodecSpecificDataSize); 122703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 122803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset, 122903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber "\x00\x00\x00\x01", 4); 123003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 123103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size); 123203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 123303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 123403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 123503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 123603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (count == 2) { 123703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber void *tmp = mCodecSpecificData; 123803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size = mCodecSpecificDataSize; 123903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = NULL; 124003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 0; 124103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 124203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 124303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)tmp, size); 124403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber free(tmp); 124503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber tmp = NULL; 1246be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 1247548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1248548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 124903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 125003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 125103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1254a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mGotAllCodecSpecificData) { 1255a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mGotAllCodecSpecificData = true; 1256a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1257a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1258d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 1259d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 1260d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 1261d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 1262d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 1263d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 1264d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 1265d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 1266d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 1267d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 12681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 1269e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 12708644c14618d30d9e57a69df40ed939986ebf02c4James Dong size_t sampleSize; 12711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong sampleSize = mIsAvc 127203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 1273d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong ? copy->range_length() + 4 127403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 1275d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong ? copy->range_length() + 2 127603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 1277d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong : copy->range_length(); 1278050b28a593350047845a45a14cc5026221ac1620James Dong 1279d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 12808644c14618d30d9e57a69df40ed939986ebf02c4James Dong mEstimatedTrackSizeBytes += sampleSize; 1281d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 1282d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 1283d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1284d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1285d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 1286d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 1287d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1288d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1289d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1290050b28a593350047845a45a14cc5026221ac1620James Dong 1291d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 1292d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 1293d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1294d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 1295d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1296d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 12978644c14618d30d9e57a69df40ed939986ebf02c4James Dong if (mSampleSizes.empty()) { 1298f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 1299f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 13003c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 130148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 1302a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 1303c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong previousPausedDurationUs += (timestampUs - mTrackDurationUs - lastDurationUs); 1304a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 1305a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1306a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1307a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 1308a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong LOGV("time stamp: %lld and previous paused duration %lld", 1309a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs, previousPausedDurationUs); 1310c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 1311c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 13123b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 13133b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 13148644c14618d30d9e57a69df40ed939986ebf02c4James Dong mSampleSizes.push_back(sampleSize); 1315ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong ++mNumSamples; 1316ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples > 2) { 13178644c14618d30d9e57a69df40ed939986ebf02c4James Dong if (lastDurationUs != timestampUs - lastTimestampUs) { 13188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong SttsTableEntry sttsEntry(sampleCount, lastDurationUs); 1319be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSttsTableEntries.push_back(sttsEntry); 1320be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 1321be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1322be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 1323be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1324be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1325be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 1326ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples >= 2 && previousSampleSize != sampleSize) { 1327be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 1328be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 13298644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 1330be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 13318644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 13328644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1334d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 1335ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mStssTableEntries.push_back(mNumSamples); 1336d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 1337d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 133893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 133993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 134093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 134193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 1342faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 134393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 134458ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mOwner->numTracks() == 1) { 13451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 134658ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 134758ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mChunkOffsets.empty()) { 134858ae9c530247668f8af36e30d228c716c226b3d4James Dong mChunkOffsets.push_back(offset); 134958ae9c530247668f8af36e30d228c716c226b3d4James Dong } 135058ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 135158ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 135258ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 135358ae9c530247668f8af36e30d228c716c226b3d4James Dong } 135413aec890216948b0c364f8f92792129d0335f506James Dong 135513aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 135613aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 135713aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(++nChunks, 1, 1); 135813aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 13591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 136013aec890216948b0c364f8f92792129d0335f506James Dong } else { 136113aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 136213aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 136313aec890216948b0c364f8f92792129d0335f506James Dong } else { 136413aec890216948b0c364f8f92792129d0335f506James Dong if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 136513aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 13668644c14618d30d9e57a69df40ed939986ebf02c4James Dong if (collectStats) { 13678644c14618d30d9e57a69df40ed939986ebf02c4James Dong mChunkDurations.push_back(timestampUs - chunkTimestampUs); 13688644c14618d30d9e57a69df40ed939986ebf02c4James Dong } 136913aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 137013aec890216948b0c364f8f92792129d0335f506James Dong (--(mStscTableEntries.end()))->samplesPerChunk != 137113aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size()) { 137213aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(nChunks, 137313aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size(), 1); 137413aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 137513aec890216948b0c364f8f92792129d0335f506James Dong } 13761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 137713aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 137813aec890216948b0c364f8f92792129d0335f506James Dong } 137913aec890216948b0c364f8f92792129d0335f506James Dong } 138013aec890216948b0c364f8f92792129d0335f506James Dong } 138113aec890216948b0c364f8f92792129d0335f506James Dong 138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 138325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 13848644c14618d30d9e57a69df40ed939986ebf02c4James Dong if (mSampleSizes.empty()) { 138593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong err = UNKNOWN_ERROR; 1386f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 1387faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong mOwner->trackProgressStatus(this, -1, err); 1388be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 138913aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 139058ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mOwner->numTracks() == 1) { 1391ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong StscTableEntry stscEntry(1, mNumSamples, 1); 139258ae9c530247668f8af36e30d228c716c226b3d4James Dong mStscTableEntries.push_back(stscEntry); 139358ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 139413aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 139513aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1); 139613aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 13971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 139813aec890216948b0c364f8f92792129d0335f506James Dong } 139913aec890216948b0c364f8f92792129d0335f506James Dong 1400be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 1401be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 1402be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 1403ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples == 1) { 14048f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 1405be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1406be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 1407be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 14088f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong SttsTableEntry sttsEntry(sampleCount, lastDurationUs); 1409be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSttsTableEntries.push_back(sttsEntry); 1410c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 141125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 14121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. Max write time: %lld us - %s", 14131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong count, nZeroLengthFrames, mNumSamples, mMaxWriteTimeUs, mIsAudio? "audio": "video"); 1414365a963142093a1cd8efdcea76b5f65096a5b115James Dong 14151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong logStatisticalData(mIsAudio); 1416365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1417365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1418faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 1419faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong LOGV("trackProgressStatus: %lld us", timeUs); 1420215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 1421215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 142293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Fire time tracking progress status at %lld us", timeUs); 1423faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err); 142493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 142593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 142693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 142793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1428faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 1429faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong const MPEG4Writer::Track* track, int64_t timeUs, status_t err) { 1430faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 1431faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong int32_t nTracks = mTracks.size(); 1432faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong CHECK(nTracks >= 1); 1433faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong CHECK(nTracks < 64); // Arbitrary number 1434faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1435faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong int32_t trackNum = 0; 1436faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong#if 0 1437faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // In the worst case, we can put the trackNum 1438faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // along with MEDIA_RECORDER_INFO_COMPLETION_STATUS 1439faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // to report the progress. 1440faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong for (List<Track *>::iterator it = mTracks.begin(); 1441faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong it != mTracks.end(); ++it, ++trackNum) { 1442faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (track == (*it)) { 1443faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong break; 1444faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 1445faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 1446faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong#endif 1447faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong CHECK(trackNum < nTracks); 1448faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum <<= 16; 1449faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1450faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 1451faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 1452faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 1453faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong notify(MEDIA_RECORDER_EVENT_ERROR, 1454faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum | MEDIA_RECORDER_ERROR_UNKNOWN, 1455faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 1456faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 1457faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 1458faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1459faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 1460faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 1461faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong notify(MEDIA_RECORDER_EVENT_INFO, 1462faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS, 1463faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 1464faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 1465faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 1466faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 1467faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong notify(MEDIA_RECORDER_EVENT_INFO, 1468faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS, 1469faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 1470faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 1471faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 1472faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1473215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dongvoid MPEG4Writer::Track::findMinAvgMaxSampleDurationMs( 1474215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t *min, int32_t *avg, int32_t *max) { 14758644c14618d30d9e57a69df40ed939986ebf02c4James Dong CHECK(!mSampleSizes.empty()); 1476c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int32_t avgSampleDurationMs = mTrackDurationUs / 1000 / mNumSamples; 1477215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t minSampleDurationMs = 0x7FFFFFFF; 1478215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t maxSampleDurationMs = 0; 1479365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1480365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != mSttsTableEntries.end(); ++it) { 14818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t sampleDurationMs = 14828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000; 1483215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (sampleDurationMs > maxSampleDurationMs) { 1484215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong maxSampleDurationMs = sampleDurationMs; 1485215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong } else if (sampleDurationMs < minSampleDurationMs) { 1486215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong minSampleDurationMs = sampleDurationMs; 1487365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1488215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong LOGI("sample duration: %d ms", sampleDurationMs); 1489365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1490215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(minSampleDurationMs != 0); 1491215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(avgSampleDurationMs != 0); 1492215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(maxSampleDurationMs != 0); 1493215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong *min = minSampleDurationMs; 1494215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong *avg = avgSampleDurationMs; 1495215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong *max = maxSampleDurationMs; 1496365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1497365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1498365a963142093a1cd8efdcea76b5f65096a5b115James Dong// Don't count the last duration 1499365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) { 1500365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t duration = mOwner->interleaveDuration(); 1501365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t minChunkDuration = duration; 1502365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t maxChunkDuration = duration; 1503365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (mChunkDurations.size() > 1) { 1504365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<int64_t>::iterator it = mChunkDurations.begin(); 1505365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != --mChunkDurations.end(); ++it) { 1506365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (minChunkDuration > (*it)) { 1507365a963142093a1cd8efdcea76b5f65096a5b115James Dong minChunkDuration = (*it); 1508365a963142093a1cd8efdcea76b5f65096a5b115James Dong } else if (maxChunkDuration < (*it)) { 1509365a963142093a1cd8efdcea76b5f65096a5b115James Dong maxChunkDuration = (*it); 1510365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1511365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1512365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1513365a963142093a1cd8efdcea76b5f65096a5b115James Dong *min = minChunkDuration; 1514365a963142093a1cd8efdcea76b5f65096a5b115James Dong *max = maxChunkDuration; 1515365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1516365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1517365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::logStatisticalData(bool isAudio) { 1518c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (mTrackDurationUs <= 0 || mSampleSizes.empty()) { 1519365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("nothing is recorded"); 1520365a963142093a1cd8efdcea76b5f65096a5b115James Dong return; 1521365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1522365a963142093a1cd8efdcea76b5f65096a5b115James Dong 15238644c14618d30d9e57a69df40ed939986ebf02c4James Dong bool collectStats = collectStatisticalData(); 1524365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1525365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (collectStats) { 1526215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong LOGI("%s track - duration %lld us, total %d frames", 1527c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong isAudio? "audio": "video", mTrackDurationUs, 1528ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mNumSamples); 1529215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t min, avg, max; 1530215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong findMinAvgMaxSampleDurationMs(&min, &avg, &max); 1531215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max); 1532215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (!isAudio) { 1533215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong float avgFps = 1000.0 / avg; 1534215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong float minFps = 1000.0 / max; 1535215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong float maxFps = 1000.0 / min; 1536365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f", 1537215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong minFps, avgFps, maxFps); 1538365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1539365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1540365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t totalBytes = 0; 15418644c14618d30d9e57a69df40ed939986ebf02c4James Dong for (List<size_t>::iterator it = mSampleSizes.begin(); 15428644c14618d30d9e57a69df40ed939986ebf02c4James Dong it != mSampleSizes.end(); ++it) { 15438644c14618d30d9e57a69df40ed939986ebf02c4James Dong totalBytes += (*it); 1544365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1545c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong float bitRate = (totalBytes * 8000000.0) / mTrackDurationUs; 1546365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("avg bit rate (bps): %.2f", bitRate); 1547365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1548365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t duration = mOwner->interleaveDuration(); 1549365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (duration != 0) { // If interleaving is enabled 1550365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t minChunk, maxChunk; 1551365a963142093a1cd8efdcea76b5f65096a5b115James Dong findMinMaxChunkDurations(&minChunk, &maxChunk); 1552365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld", 1553365a963142093a1cd8efdcea76b5f65096a5b115James Dong minChunk, duration, maxChunk); 1554365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1555365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 155613aec890216948b0c364f8f92792129d0335f506James Dong} 155713aec890216948b0c364f8f92792129d0335f506James Dong 15581c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 15591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("bufferChunk"); 15601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 15611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t startTimeUs = systemTime() / 1000; 15621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 15631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 156413aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 15651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t endTimeUs = systemTime() / 1000; 15661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mMaxWriteTimeUs < endTimeUs - startTimeUs) { 15671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMaxWriteTimeUs = endTimeUs - startTimeUs; 15681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 156920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 157020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15713b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 1572c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 157320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 157420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1575d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 1576d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 1577d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1578d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 15791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader( 15801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t trackID, bool use32BitOffset) { 158120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 158220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findCString(kKeyMIMEType, &mime); 15830c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 158420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("%s track time scale: %d", 15861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 15878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 158920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 15908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 15918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 159220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 159320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("trak"); 159420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 159520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("tkhd"); 15961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Flags = 7 to indicate that the track is enabled, and 15971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // part of the presentation 15981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0x07); // version=0, flags=7 159920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 160020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 160120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(trackID); 160220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 16038f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t tkhdDuration = 16048f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 16058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 160620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 160720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 160820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // layer 160920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // alternate group 16101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 161120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 161220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 161320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); // matrix 161420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 161520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 161620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 161720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); 161820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 161920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 162020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 162120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x40000000); 162220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAudio) { 162420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 162520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 162620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 162720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 162820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 16300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1632050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 1633050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 163420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 163520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // tkhd 163620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1637f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 1638f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (mStartTimestampUs != moovStartTimeUs) { 16393c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("edts"); 16403c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("elst"); 16411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0); // version=0, flags=0: 32-bit time 16421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(2); // never ends with an empty list 16438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 16448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // First elst entry: specify the starting time offset 16458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t offsetUs = mStartTimestampUs - moovStartTimeUs; 16468f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6; 16478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(seg); // in mvhd timecale 16488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(-1); // starting time offset 16498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(1 << 16); // rate = 1.0 16508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 16518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // Second elst entry: specify the track duration 16528f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 16538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(seg); // in mvhd timescale 16541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0); 16551acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); 16563c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 16573c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 16583c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 16593c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 166020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdia"); 166120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 166220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdhd"); 166320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 166420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 166520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 16668f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(mTimeScale); // media timescale 16678f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 16688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(mdhdDuration); // use media timescale 16691acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Language follows the three letter standard ISO-639-2/T 16701acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // 'e', 'n', 'g' for "English", for instance. 16711acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Each character is packed as the difference between its ASCII value and 0x60. 16721acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // For "English", these are 00101, 01110, 00111. 16731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // XXX: Where is the padding bit located: 0x15C7? 16741acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt16(0); // language code 167520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 167620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 167720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 167820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("hdlr"); 167920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1680050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // component type: should be mhlr 16811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 168220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 168320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 168420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 16851acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Removing "r" for the name string just makes the string 4 byte aligned 16861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 168720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 168820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 168920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("minf"); 16901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAudio) { 169120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("smhd"); 169220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 169320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // balance 169420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 169520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 169620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 169720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("vmhd"); 16981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0x01); // version=0, flags=1 169920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // graphics mode 170020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // opcolor 170120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 170220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 170320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 170420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1705050b28a593350047845a45a14cc5026221ac1620James Dong 1706050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dinf"); 1707050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dref"); 1708050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 17091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1); // entry count (either url or urn) 17101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // The table index here refers to the sample description index 17111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // in the sample table entries. 1712050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("url "); 17131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 1714050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // url 1715050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dref 1716050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dinf 1717050b28a593350047845a45a14cc5026221ac1620James Dong 171820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stbl"); 171920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 172020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsd"); 172120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 172220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); // entry count 17231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAudio) { 172425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber const char *fourcc = NULL; 172518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 172625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "samr"; 172718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 172825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "sawb"; 1729050b28a593350047845a45a14cc5026221ac1620James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1730050b28a593350047845a45a14cc5026221ac1620James Dong fourcc = "mp4a"; 173125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } else { 173225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 173325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber CHECK(!"should not be here, unknown mime type."); 173425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 173525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 173625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mOwner->beginBox(fourcc); // audio format 173720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 173820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 1739050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x1); // data ref index 174020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 174120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 1742050b28a593350047845a45a14cc5026221ac1620James Dong int32_t nChannels; 1743050b28a593350047845a45a14cc5026221ac1620James Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 1744050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(nChannels); // channel count 174520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(16); // sample size 174620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 174720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 174820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 174920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t samplerate; 175020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 17510c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 175220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 175320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(samplerate << 16); 1754050b28a593350047845a45a14cc5026221ac1620James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1755050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("esds"); 1756050b28a593350047845a45a14cc5026221ac1620James Dong 1757050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1758050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x03); // ES_DescrTag 1759050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 1760050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x0000);// ES_ID 1761050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); 1762050b28a593350047845a45a14cc5026221ac1620James Dong 1763050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 1764050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 1765050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 1766050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x15); // streamType AudioStream 1767050b28a593350047845a45a14cc5026221ac1620James Dong 1768050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x03); // XXX 1769050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); // buffer size 24-bit 1770050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // max bit rate 1771050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // avg bit rate 1772050b28a593350047845a45a14cc5026221ac1620James Dong 1773050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 1774050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(mCodecSpecificDataSize); 1775050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 1776050b28a593350047845a45a14cc5026221ac1620James Dong 1777050b28a593350047845a45a14cc5026221ac1620James Dong static const uint8_t kData2[] = { 1778050b28a593350047845a45a14cc5026221ac1620James Dong 0x06, // SLConfigDescriptorTag 1779050b28a593350047845a45a14cc5026221ac1620James Dong 0x01, 1780050b28a593350047845a45a14cc5026221ac1620James Dong 0x02 1781050b28a593350047845a45a14cc5026221ac1620James Dong }; 1782050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(kData2, sizeof(kData2)); 1783050b28a593350047845a45a14cc5026221ac1620James Dong 1784050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // esds 17855aff464f67322cd13dc8ed165806971cfff2e4d5James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 17865aff464f67322cd13dc8ed165806971cfff2e4d5James Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 17875aff464f67322cd13dc8ed165806971cfff2e4d5James Dong // 3gpp2 Spec AMRSampleEntry fields 17885aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->beginBox("damr"); 17895aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeCString(" "); // vendor: 4 bytes 17905aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt8(0); // decoder version 17915aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 17925aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt8(0); // mode change period 17935aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt8(1); // frames per sample 17945aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->endBox(); 1795050b28a593350047845a45a14cc5026221ac1620James Dong } 179620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 179720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 179818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 179920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mp4v"); 180018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 180120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("s263"); 180230ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 180330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avc1"); 180420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 180525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 18060c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!"should not be here, unknown mime type."); 180720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 180820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 180920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 181020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 18111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt16(1); // data ref index 181220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 181320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 181420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 181520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 181620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 181720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 181820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 181920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 182020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 18210c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 182220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 182320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(width); 182420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(height); 182520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // horiz resolution 182620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // vert resolution 182720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 182820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(1); // frame count 182920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(" ", 32); 183020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x18); // depth 183120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(-1); // predefined 183220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18330c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(23 + mCodecSpecificDataSize < 128); 183420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 183518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 183620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("esds"); 183720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 183820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 183920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 184020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x03); // ES_DescrTag 184120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(23 + mCodecSpecificDataSize); 184220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x0000); // ES_ID 184320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x1f); 184420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 184520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x04); // DecoderConfigDescrTag 184620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(15 + mCodecSpecificDataSize); 184720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x11); // streamType VisualStream 184920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData[] = { 185120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 0x77, 0x00, 185220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00, 185320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00 185420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 185520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData, sizeof(kData)); 1856050b28a593350047845a45a14cc5026221ac1620James Dong 185720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 185820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 185920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(mCodecSpecificDataSize); 186020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 186120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 186220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData2[] = { 186320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x06, // SLConfigDescriptorTag 186420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 186520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x02 186620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 186720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData2, sizeof(kData2)); 186820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 186920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // esds 187018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 187120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("d263"); 187220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 187320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // vendor 187420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // decoder version 187520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(10); // level: 10 187620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // profile: 0 187720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 187820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // d263 187930ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 188030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avcC"); 188130ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 188230ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // avcC 188320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 188430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 18851acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->beginBox("pasp"); 18861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // This is useful if the pixel is not square 18871acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // hspacing 18881acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // vspacing 18891acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->endBox(); // pasp 189030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // mp4v, s263 or avc1 189120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 189220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsd 189320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 189420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stts"); 189520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1896be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(mSttsTableEntries.size()); 1897be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1898be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSttsTableEntries.end(); ++it) { 1899be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleCount); 19008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t dur = (it->sampleDurationUs * mTimeScale + 5E5) / 1E6; 19018f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(dur); 190220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 190320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stts 190420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!mIsAudio) { 1906050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("stss"); 1907050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1908050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames 1909050b28a593350047845a45a14cc5026221ac1620James Dong for (List<int32_t>::iterator it = mStssTableEntries.begin(); 1910050b28a593350047845a45a14cc5026221ac1620James Dong it != mStssTableEntries.end(); ++it) { 1911050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(*it); 1912050b28a593350047845a45a14cc5026221ac1620James Dong } 1913050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // stss 1914050b28a593350047845a45a14cc5026221ac1620James Dong } 1915050b28a593350047845a45a14cc5026221ac1620James Dong 191620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsz"); 191720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1918be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 19198644c14618d30d9e57a69df40ed939986ebf02c4James Dong List<size_t>::iterator it = mSampleSizes.begin(); 19208644c14618d30d9e57a69df40ed939986ebf02c4James Dong mOwner->writeInt32(*it); // default sample size 1921be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1922be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(0); 1923be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1924ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mOwner->writeInt32(mNumSamples); 1925be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (!mSamplesHaveSameSize) { 19268644c14618d30d9e57a69df40ed939986ebf02c4James Dong for (List<size_t>::iterator it = mSampleSizes.begin(); 19278644c14618d30d9e57a69df40ed939986ebf02c4James Dong it != mSampleSizes.end(); ++it) { 19288644c14618d30d9e57a69df40ed939986ebf02c4James Dong mOwner->writeInt32(*it); 1929be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 193020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 193120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsz 193220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 193320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsc"); 193420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 193513aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(mStscTableEntries.size()); 193613aec890216948b0c364f8f92792129d0335f506James Dong for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 193713aec890216948b0c364f8f92792129d0335f506James Dong it != mStscTableEntries.end(); ++it) { 193813aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->firstChunk); 193913aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->samplesPerChunk); 194013aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->sampleDescriptionId); 194120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 194220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsc 19431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 194420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 194513aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(mChunkOffsets.size()); 194613aec890216948b0c364f8f92792129d0335f506James Dong for (List<off_t>::iterator it = mChunkOffsets.begin(); 194713aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkOffsets.end(); ++it) { 19481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (use32BitOffset) { 19491acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(static_cast<int32_t>(*it)); 19501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 19511acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt64((*it)); 19521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 195320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 19548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->endBox(); // stco or co64 195520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 195620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stbl 19571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->endBox(); // minf 195820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // mdia 195920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // trak 196020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 196120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 196220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 1963