MPEG4Writer.cpp revision 8f5f2fcee5c12d08df71d17017410c50951fc2e3
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); 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 59693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 61a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 62a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 633b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t mMaxTimeStampUs; 64d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 658f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber struct SampleInfo { 7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t size; 718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t timestampUs; 7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 7313aec890216948b0c364f8f92792129d0335f506James Dong List<SampleInfo> mSampleInfos; 74be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong bool mSamplesHaveSameSize; 75be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 7613aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 7713aec890216948b0c364f8f92792129d0335f506James Dong List<off_t> mChunkOffsets; 7813aec890216948b0c364f8f92792129d0335f506James Dong 7913aec890216948b0c364f8f92792129d0335f506James Dong struct StscTableEntry { 8013aec890216948b0c364f8f92792129d0335f506James Dong 8113aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 8213aec890216948b0c364f8f92792129d0335f506James Dong : firstChunk(chunk), 8313aec890216948b0c364f8f92792129d0335f506James Dong samplesPerChunk(samples), 8413aec890216948b0c364f8f92792129d0335f506James Dong sampleDescriptionId(id) {} 8513aec890216948b0c364f8f92792129d0335f506James Dong 8613aec890216948b0c364f8f92792129d0335f506James Dong uint32_t firstChunk; 8713aec890216948b0c364f8f92792129d0335f506James Dong uint32_t samplesPerChunk; 8813aec890216948b0c364f8f92792129d0335f506James Dong uint32_t sampleDescriptionId; 8913aec890216948b0c364f8f92792129d0335f506James Dong }; 9013aec890216948b0c364f8f92792129d0335f506James Dong List<StscTableEntry> mStscTableEntries; 9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 92050b28a593350047845a45a14cc5026221ac1620James Dong List<int32_t> mStssTableEntries; 93365a963142093a1cd8efdcea76b5f65096a5b115James Dong List<int64_t> mChunkDurations; 94050b28a593350047845a45a14cc5026221ac1620James Dong 95be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong struct SttsTableEntry { 96be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 978f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong SttsTableEntry(uint32_t count, uint32_t durationUs) 988f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong : sampleCount(count), sampleDurationUs(durationUs) {} 99be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 100be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t sampleCount; 1018f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong uint32_t sampleDurationUs; 102be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong }; 103be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SttsTableEntry> mSttsTableEntries; 104be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 107548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 10893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 1113c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 11293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 11393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 11493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t mTrackEveryNumberOfFrames; 11525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void threadEntry(); 11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t makeAVCCodecSpecificData( 12003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size); 12113aec890216948b0c364f8f92792129d0335f506James Dong void writeOneChunk(bool isAvc); 122215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 123215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 12493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void trackProgressStatus(int32_t nFrames, int64_t timeUs); 12593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 12603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 127215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Utilities for collecting statistical data 128215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong void logStatisticalData(bool isAudio); 129215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong void findMinAvgMaxSampleDurationMs( 130215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t *min, int32_t *avg, int32_t *max); 131215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong void findMinMaxChunkDurations(int64_t *min, int64_t *max); 132215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 13319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 13419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR 1 14003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFile(fopen(filename, "wb")), 1431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 144a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 145a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 14713aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1487837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 14913aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs(500000) { 1500c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mFile != NULL); 15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15330ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 15430ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mFile(fdopen(fd, "wb")), 1551acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 156a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 157a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 15830ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 15913aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1607837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 16113aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs(500000) { 16230ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(mFile != NULL); 16330ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 16430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 16520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 17020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 17220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1752dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 17625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track *track = new Track(this, source); 17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 1782dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 1792dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 183a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 184a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 18593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 186a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 187a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 188a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 189a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 190a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 191a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 192a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 193a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 194a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 195a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 196a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 197a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 198a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1992dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 2002dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 2012dec2b5be2056c6d9428897dc672185872d30d17James Dong // 2022dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 2032dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 2042dec2b5be2056c6d9428897dc672185872d30d17James Dong // Currently, lets set to 0.4% for now. 2052dec2b5be2056c6d9428897dc672185872d30d17James Dong 2062dec2b5be2056c6d9428897dc672185872d30d17James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB, 2072dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 2082dec2b5be2056c6d9428897dc672185872d30d17James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 4 2092dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 2102dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 2112dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 2122dec2b5be2056c6d9428897dc672185872d30d17James Dong 2132dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 2142dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 2152dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 2162dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024; // 4 KB 2172dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 2182dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 2192dec2b5be2056c6d9428897dc672185872d30d17James Dong 2202dec2b5be2056c6d9428897dc672185872d30d17James Dong if (mMaxFileSizeLimitBytes != 0) { 2212dec2b5be2056c6d9428897dc672185872d30d17James Dong size = mMaxFileSizeLimitBytes * 4 / 1000; 2222dec2b5be2056c6d9428897dc672185872d30d17James Dong } else if (mMaxFileDurationLimitUs != 0) { 2232dec2b5be2056c6d9428897dc672185872d30d17James Dong if (bitRate <= 0) { 2242dec2b5be2056c6d9428897dc672185872d30d17James Dong // We could not estimate the file size since bitRate is not set. 2252dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 2262dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 2272dec2b5be2056c6d9428897dc672185872d30d17James Dong size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000); 2282dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2292dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2302dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 2312dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 2322dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2332dec2b5be2056c6d9428897dc672185872d30d17James Dong 2342dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 2352dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 2362dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 2372dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 2382dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2392dec2b5be2056c6d9428897dc672185872d30d17James Dong 2402dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 2412dec2b5be2056c6d9428897dc672185872d30d17James Dong " moov size %lld bytes", 2422dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 2432dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 2442dec2b5be2056c6d9428897dc672185872d30d17James Dong} 2452dec2b5be2056c6d9428897dc672185872d30d17James Dong 2462dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 24825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2512dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 2522dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 2532dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 2542dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 2552dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 2562dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2572dec2b5be2056c6d9428897dc672185872d30d17James Dong 2582dec2b5be2056c6d9428897dc672185872d30d17James Dong // System property can overwrite the file offset bits parameter 2592dec2b5be2056c6d9428897dc672185872d30d17James Dong char value[PROPERTY_VALUE_MAX]; 2602dec2b5be2056c6d9428897dc672185872d30d17James Dong if (property_get("media.stagefright.record-64bits", value, NULL) 2612dec2b5be2056c6d9428897dc672185872d30d17James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 2622dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 2632dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2642dec2b5be2056c6d9428897dc672185872d30d17James Dong 265065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 26693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 267a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 268a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 269a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 27093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 271a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 272a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 273a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 274a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 2768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 2778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 2788f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 2798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 2808f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("movie time scale: %d", mTimeScale); 2818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 2827837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = true; 2837837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 2847837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 2857837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 2867837c17063a4c50bc856ba59418516fdab731de7James Dong 28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("ftyp"); 28893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 28993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t fileType; 29093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (param && param->findInt32(kKeyFileType, &fileType) && 29193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong fileType != OUTPUT_FORMAT_MPEG_4) { 29293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("3gp4"); 29393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } else { 29493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("isom"); 29593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 29693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 29993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("3gp4"); 30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); 30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3027837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3047837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 3052dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 3062dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 3072dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 3082dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3092dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 3107837c17063a4c50bc856ba59418516fdab731de7James Dong } 3117837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mEstimatedMoovBoxSize >= 8); 3127837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 3137837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize); 3147837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 3157837c17063a4c50bc856ba59418516fdab731de7James Dong 3167837c17063a4c50bc856ba59418516fdab731de7James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 3177837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 3187837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 3191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 3201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 3211acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 3221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 3231acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 32493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = startTracks(param); 325a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 326a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 328a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 32925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 332a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::pause() { 333a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mFile == NULL) { 334a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return; 335a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 336a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 337a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 338a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 339a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it)->pause(); 340a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 341a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 342a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() { 34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 34620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->stop(); 35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 3548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 3558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3597837c17063a4c50bc856ba59418516fdab731de7James Dong 36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 3611acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 3621acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 3631acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 3641acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fwrite(&size, 1, 4, mFile); 3651acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 3661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fseeko(mFile, mMdatOffset + 8, SEEK_SET); 3671acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int64_t size = mOffset - mMdatOffset; 3681acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 3691acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fwrite(&size, 1, 8, mFile); 3701acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 3717837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 3747837c17063a4c50bc856ba59418516fdab731de7James Dong const off_t moovOffset = mOffset; 3757837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = true; 3767837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 3777837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 3787837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 3798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t duration = (maxDurationUs * mTimeScale) / 1E6; 38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("moov"); 38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("mvhd"); 38420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // version=0, flags=0 38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // creation time 38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // modification time 3878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong writeInt32(mTimeScale); // mvhd timescale 3881acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(duration); 3891acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(0x10000); // rate: 1.0 39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0x100); // volume 39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0); // reserved 39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 39420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // matrix 39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 39720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); 39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x40000000); 40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 40520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mTracks.size() + 1); // nextTrackID 41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // mvhd 41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t id = 1; 41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it, ++id) { 4151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong (*it)->writeTrackHeader(id, mUse32BitOffset); 41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // moov 41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4197837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 4207837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 4217837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 4227837c17063a4c50bc856ba59418516fdab731de7James Dong 4237837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 4247837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 4257837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 4267837c17063a4c50bc856ba59418516fdab731de7James Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); 4277837c17063a4c50bc856ba59418516fdab731de7James Dong 4287837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 4292dec2b5be2056c6d9428897dc672185872d30d17James Dong fseeko(mFile, mOffset, SEEK_SET); 4307837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 4317837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 4327837c17063a4c50bc856ba59418516fdab731de7James Dong 4337837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 4347837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 4357837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 4367837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 4372dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 4382dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("The mp4 file will not be streamable."); 4397837c17063a4c50bc856ba59418516fdab731de7James Dong } 4407837c17063a4c50bc856ba59418516fdab731de7James Dong 4410c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4437837c17063a4c50bc856ba59418516fdab731de7James Dong fflush(mFile); 44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fclose(mFile); 44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFile = NULL; 446a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = false; 44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 44913aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 45013aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 45113aec890216948b0c364f8f92792129d0335f506James Dong return OK; 45213aec890216948b0c364f8f92792129d0335f506James Dong} 45313aec890216948b0c364f8f92792129d0335f506James Dong 45413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 45513aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 45613aec890216948b0c364f8f92792129d0335f506James Dong} 45713aec890216948b0c364f8f92792129d0335f506James Dong 45813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 45913aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 46013aec890216948b0c364f8f92792129d0335f506James Dong} 46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 46213aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t old_offset = mOffset; 46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 46520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 46620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1, buffer->range_length(), mFile); 46720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 46820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 47303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 47403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 47503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 47603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 47703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 47803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 47903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 48003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 48103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 48203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 48303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 48403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 48503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 48603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 48713aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 48830ab66297501757d745b9ae10da61adcd891f497Andreas Huber off_t old_offset = mOffset; 48930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 49030ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 49103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 49203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 49303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t x = length >> 24; 49403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 49503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 16) & 0xff; 49603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 49703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 8) & 0xff; 49803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 49903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = length & 0xff; 50003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 50103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 50230ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(length < 65536); 50330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 50430ab66297501757d745b9ae10da61adcd891f497Andreas Huber uint8_t x = length >> 8; 50530ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 50630ab66297501757d745b9ae10da61adcd891f497Andreas Huber x = length & 0xff; 50730ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 50803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 50930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 51030ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 51130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1, length, mFile); 51230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 51303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 51403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mOffset += length + 4; 51503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 51630ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset += length + 2; 51703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 51830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 51930ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 52030ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 52130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 5227837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 5237837c17063a4c50bc856ba59418516fdab731de7James Dong const void *ptr, size_t size, size_t nmemb, FILE *stream) { 5247837c17063a4c50bc856ba59418516fdab731de7James Dong 5257837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 5267837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 5271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 5281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 5297837c17063a4c50bc856ba59418516fdab731de7James Dong for (List<off_t>::iterator it = mBoxes.begin(); 5307837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 5317837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 5327837c17063a4c50bc856ba59418516fdab731de7James Dong } 5337837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 5347837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); 5357837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 5367837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 5377837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 5387837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 5397837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 5407837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 5417837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = false; 5427837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 5437837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 5447837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 5457837c17063a4c50bc856ba59418516fdab731de7James Dong } 5467837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 5477837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 5487837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 5497837c17063a4c50bc856ba59418516fdab731de7James Dong } 5507837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 5517837c17063a4c50bc856ba59418516fdab731de7James Dong} 5527837c17063a4c50bc856ba59418516fdab731de7James Dong 55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 5540c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5567837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 5577837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 5640c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset = *--mBoxes.end(); 56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5697837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 5707837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 5717837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 5727837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 5737837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, offset, SEEK_SET); 5747837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 5757837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 5767837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 5777837c17063a4c50bc856ba59418516fdab731de7James Dong } 57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 5817837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 1, mFile); 58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 5867837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 2, mFile); 58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 5917837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 4, mFile); 59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 5967837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 8, mFile); 59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 6017837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, n + 1, mFile); 60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 6050c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 6067837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, 4, mFile); 60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 6107837c17063a4c50bc856ba59418516fdab731de7James Dong write(data, 1, size, mFile); 61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 613d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 614d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 615d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 616d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 617d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 618d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 619956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 620d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 621d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 622d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 623d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 624d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes); 625d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 626d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 627d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 628d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 629d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 630d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 631d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 632d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 633d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 634d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 635d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 636d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 637d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 638d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 639d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 640d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 641d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 64225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 64325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 64425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 64525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 64625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 64725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 64825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 64925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 65025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 65125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 65225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 65325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 65425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 655f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 656f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("setStartTimestampUs: %lld", timeUs); 657f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong CHECK(timeUs >= 0); 6583c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 659065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 660f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 661f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("Earliest track starting time: %lld", mStartTimestampUs); 6623c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 6633c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 6643c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 665f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 6663c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 6673c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 6683c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 6693c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 67058ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 67158ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 67258ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 67358ae9c530247668f8af36e30d228c716c226b3d4James Dong} 67458ae9c530247668f8af36e30d228c716c226b3d4James Dong 67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 67720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 67825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber MPEG4Writer *owner, const sp<MediaSource> &source) 67920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 68025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 68120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 68220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 683a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 684a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 6853b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs(0), 686956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 687be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 68925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 690548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 69125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS(false) { 69219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 6938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 6948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!mMeta->findInt32(kKeyTimeScale, &mTimeScale)) { 6958f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 6968f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 6978f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 69819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 69919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 70019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 70119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 70219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 70319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 70419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 70519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 70619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 70719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 70819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 70919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 71019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 71119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 71219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 71319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 71419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 71519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 71619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 71719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 71819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 71919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 72019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 72119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 72219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 72319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 72419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 72519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 72619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 72719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 72819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 74193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("initTrackingProgressStatus"); 74293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 74393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 74493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 74593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryNumberOfFrames = 0; 74693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 74793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 74893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 74993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Receive request to track progress status for every %lld us", timeUs); 75093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 75193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 75293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 75393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 75493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 75593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t nFrames; 75693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt32(kKeyTrackFrameStatus, &nFrames)) { 75793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Receive request to track progress status for every %d frames", nFrames); 75893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryNumberOfFrames = nFrames; 75993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 76093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 76193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 76293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 76393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 76493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 765a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 766a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 767a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 768a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 769a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 77025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 77193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 77219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 77319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 77419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 77519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 77693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 77793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 778f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 779f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 780f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 78125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 78225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 78325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 78425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 78720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 78920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 7913b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs = 0; 79225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 793956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 79525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 79620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 79725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 79825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 79920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 80020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 801a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::Track::pause() { 802a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 803a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 804a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() { 80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource->stop(); 81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 81925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 82025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 82125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track->threadEntry(); 82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 831548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h> 832548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) { 833548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber const uint8_t *data = (const uint8_t *)_data; 834548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t offset = 0; 835548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber while (offset < size) { 836548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("0x%04x ", offset); 837548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 838548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t n = size - offset; 839548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (n > 16) { 840548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber n = 16; 841548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 842548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 843548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < 16; ++i) { 844548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (i == 8) { 845548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 846548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 847548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 848548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (offset + i < size) { 849548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%02x ", data[offset + i]); 850548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 851548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 852548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 853548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 854548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 855548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 856548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 857548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < n; ++i) { 858548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (isprint(data[offset + i])) { 859548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%c", data[offset + i]); 860548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 861548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("."); 862548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 863548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 864548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 865548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("\n"); 866548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 867548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber offset += 16; 868548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 869548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber} 870548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 871548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 87203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 87303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 874548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber // hexdump(data, size); 875548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 87603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 877548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Already have codec specific data"); 87803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 87903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 88003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 88103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) { 882548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Must start with a start code"); 88303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 88403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 88503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 88603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamOffset = 4; 88703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber while (picParamOffset + 3 < size 88803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) { 88903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber ++picParamOffset; 89003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 89103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 89203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (picParamOffset + 3 >= size) { 893548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Could not find start-code for pictureParameterSet"); 89403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 89503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 89603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 89703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t seqParamSetLength = picParamOffset - 4; 89803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamSetLength = size - picParamOffset - 4; 89903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 90003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 90103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2; 90203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 90303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 90403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 90503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 90603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = 0x42; // profile 90703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = 0x80; 90803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[3] = 0x1e; // level 90903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 91003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 91103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 3; // length size == 4 bytes 91203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 91303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 1; // length size == 2 bytes 91403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 91503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 91603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[5] = 0xe0 | 1; 91703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[6] = seqParamSetLength >> 8; 91803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[7] = seqParamSetLength & 0xff; 91903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[8], &data[4], seqParamSetLength); 92003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header += 8 + seqParamSetLength; 92103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 92203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = picParamSetLength >> 8; 92303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = picParamSetLength & 0xff; 92403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength); 92503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 92603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 92703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 92803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 92920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() { 93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> meta = mSource->getFormat(); 93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber meta->findCString(kKeyMIMEType, &mime); 933050b28a593350047845a45a14cc5026221ac1620James Dong bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 934050b28a593350047845a45a14cc5026221ac1620James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 93530ab66297501757d745b9ae10da61adcd891f497Andreas Huber bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 936956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bool is_audio = !strncasecmp(mime, "audio/", 6); 93730ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 93813aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 93913aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 94013aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 94113aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 9428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t lastTimestampUs = 0; // Previous sample time stamp in ms 9438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t lastDurationUs = 0; // Between the previous two samples in ms 9448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 945be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 946a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 947d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 94820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 94993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 95193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 95513aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 959a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 960a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 961a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 962a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 963a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 964a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 965a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 966a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 967a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 96830ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 96930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 97003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 97103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 97203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 973548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 974548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 97503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (is_avc) { 97603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 97703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 97803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 97903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 980be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 98103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } else if (is_mpeg4) { 98203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 98303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 98403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 98503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 98603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 98703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 98830ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 98930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 99030ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 99130ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 99230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 993548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 99430ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 995548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && 996548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber count == 1 && is_mpeg4 && mCodecSpecificData == NULL) { 99703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI mpeg4 encoder does not properly set the 99803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // codec-specific-data flag. 99930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 100020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *data = 100120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 100220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 100320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const size_t size = buffer->range_length(); 100420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 100520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t offset = 0; 100620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (offset + 3 < size) { 100720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (data[offset] == 0x00 && data[offset + 1] == 0x00 100820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) { 100920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 101020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 101120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 101220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++offset; 101320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 101420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10150c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber // CHECK(offset + 3 < size); 1016bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber if (offset + 3 >= size) { 1017bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // XXX assume the entire first chunk of data is the codec specific 1018bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // data. 1019bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber offset = size; 1020bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber } 102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificDataSize = offset; 102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = malloc(offset); 102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber memcpy(mCodecSpecificData, data, offset); 102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->set_range(buffer->range_offset() + offset, size - offset); 102703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 102803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size == offset) { 102903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 103003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 103103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 103203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 103303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 1034548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1035548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 1036548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && is_avc && count < 3) { 103703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI video encoder does not flag codec specific data 103803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // as such and also splits up SPS and PPS across two buffers. 103903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 104003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data = 104103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 104203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 104303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t size = buffer->range_length(); 104403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 104503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber CHECK(count == 2 || mCodecSpecificData == NULL); 104603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 104703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t offset = mCodecSpecificDataSize; 104803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize += size + 4; 104903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = 105003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber realloc(mCodecSpecificData, mCodecSpecificDataSize); 105103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 105203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset, 105303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber "\x00\x00\x00\x01", 4); 105403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 105503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size); 105603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 105703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 105803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 105903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 106003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (count == 2) { 106103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber void *tmp = mCodecSpecificData; 106203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size = mCodecSpecificDataSize; 106303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = NULL; 106403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 0; 106503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 106603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 106703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)tmp, size); 106803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber free(tmp); 106903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber tmp = NULL; 1070be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 1071548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1072548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 107303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 107403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 107503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 107620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 107720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1078a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mGotAllCodecSpecificData) { 1079a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mGotAllCodecSpecificData = true; 1080a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1081a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1082d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 1083d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 1084d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 1085d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 1086d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 1087d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 1088d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 1089d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 1090d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 1091d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1092d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (is_avc) StripStartcode(copy); 1093e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 109420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber SampleInfo info; 109503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber info.size = is_avc 109603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 1097d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong ? copy->range_length() + 4 109803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 1099d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong ? copy->range_length() + 2 110003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 1101d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong : copy->range_length(); 1102050b28a593350047845a45a14cc5026221ac1620James Dong 1103d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 1104d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mEstimatedTrackSizeBytes += info.size; 1105d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 1106d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 1107d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1108d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1109d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 1110d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 1111d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1112d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1113d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1114050b28a593350047845a45a14cc5026221ac1620James Dong 1115d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 1116d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 1117d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 111848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int64_t timestampUs; 1119d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 1120d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1121d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 11223c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong if (mSampleInfos.empty()) { 1123f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 1124f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 11253c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 112648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 1127a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 11288f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - lastDurationUs); 1129a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 1130a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1131a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1132a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 1133a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong LOGV("time stamp: %lld and previous paused duration %lld", 1134a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs, previousPausedDurationUs); 11353b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber if (timestampUs > mMaxTimeStampUs) { 11363b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs = timestampUs; 11373b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 11383b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 11398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong info.timestampUs = timestampUs; 114020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSampleInfos.push_back(info); 1141be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() > 2) { 11428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (lastDurationUs != info.timestampUs - lastTimestampUs) { 11438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong SttsTableEntry sttsEntry(sampleCount, lastDurationUs); 1144be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSttsTableEntries.push_back(sttsEntry); 1145be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 1146be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1147be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 1148be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1149be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1150be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 1151be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() >= 2 && previousSampleSize != info.size) { 1152be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 1153be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1154be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong previousSampleSize = info.size; 1155be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 11568f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = info.timestampUs - lastTimestampUs; 11578f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastTimestampUs = info.timestampUs; 115820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1159d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 1160d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong mStssTableEntries.push_back(mSampleInfos.size()); 1161d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 1162d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 116393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 116493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 116593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 116693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 116793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong trackProgressStatus(mSampleInfos.size(), timestampUs); 116893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 116958ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mOwner->numTracks() == 1) { 117058ae9c530247668f8af36e30d228c716c226b3d4James Dong off_t offset = is_avc? mOwner->addLengthPrefixedSample_l(copy) 117158ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 117258ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mChunkOffsets.empty()) { 117358ae9c530247668f8af36e30d228c716c226b3d4James Dong mChunkOffsets.push_back(offset); 117458ae9c530247668f8af36e30d228c716c226b3d4James Dong } 117558ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 117658ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 117758ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 117858ae9c530247668f8af36e30d228c716c226b3d4James Dong } 117913aec890216948b0c364f8f92792129d0335f506James Dong 118013aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 118113aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 118213aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(++nChunks, 1, 1); 118313aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 118413aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 118513aec890216948b0c364f8f92792129d0335f506James Dong } else { 118613aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 118713aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 118813aec890216948b0c364f8f92792129d0335f506James Dong } else { 118913aec890216948b0c364f8f92792129d0335f506James Dong if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 119013aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 1191365a963142093a1cd8efdcea76b5f65096a5b115James Dong mChunkDurations.push_back(timestampUs - chunkTimestampUs); 119213aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 119313aec890216948b0c364f8f92792129d0335f506James Dong (--(mStscTableEntries.end()))->samplesPerChunk != 119413aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size()) { 119513aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(nChunks, 119613aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size(), 1); 119713aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 119813aec890216948b0c364f8f92792129d0335f506James Dong } 119913aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 120013aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 120113aec890216948b0c364f8f92792129d0335f506James Dong } 120213aec890216948b0c364f8f92792129d0335f506James Dong } 120313aec890216948b0c364f8f92792129d0335f506James Dong } 120413aec890216948b0c364f8f92792129d0335f506James Dong 120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 120625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1207f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong if (mSampleInfos.empty()) { 120893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong err = UNKNOWN_ERROR; 1209f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 121093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_COMPLETION_STATUS, err); 1211be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 121213aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 121358ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mOwner->numTracks() == 1) { 121458ae9c530247668f8af36e30d228c716c226b3d4James Dong StscTableEntry stscEntry(1, mSampleInfos.size(), 1); 121558ae9c530247668f8af36e30d228c716c226b3d4James Dong mStscTableEntries.push_back(stscEntry); 121658ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 121713aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 121813aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1); 121913aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 122013aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 122113aec890216948b0c364f8f92792129d0335f506James Dong } 122213aec890216948b0c364f8f92792129d0335f506James Dong 1223be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 1224be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 1225be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 1226be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() == 1) { 12278f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 1228be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1229be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 1230be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 12318f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong SttsTableEntry sttsEntry(sampleCount, lastDurationUs); 1232be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSttsTableEntries.push_back(sttsEntry); 123325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 1234956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s", 1235956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong count, nZeroLengthFrames, mSampleInfos.size(), is_audio? "audio": "video"); 1236365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1237365a963142093a1cd8efdcea76b5f65096a5b115James Dong logStatisticalData(is_audio); 1238365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1239365a963142093a1cd8efdcea76b5f65096a5b115James Dong 124093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::trackProgressStatus(int32_t nFrames, int64_t timeUs) { 124193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("trackProgressStatus: %d frames and %lld us", nFrames, timeUs); 1242215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryNumberOfFrames > 0 && 1243215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong nFrames % mTrackEveryNumberOfFrames == 0) { 124493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Fire frame tracking progress status at frame %d", nFrames); 124593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, 124693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong MEDIA_RECORDER_INFO_PROGRESS_FRAME_STATUS, 124793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong nFrames); 124893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 124993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1250215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 1251215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 125293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Fire time tracking progress status at %lld us", timeUs); 125393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, 125493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS, 125593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong timeUs / 1000); 125693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 125793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 125893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 125993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1260215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dongvoid MPEG4Writer::Track::findMinAvgMaxSampleDurationMs( 1261215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t *min, int32_t *avg, int32_t *max) { 1262215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(!mSampleInfos.empty()); 12638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t avgSampleDurationMs = mMaxTimeStampUs / 1000 / mSampleInfos.size(); 1264215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t minSampleDurationMs = 0x7FFFFFFF; 1265215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t maxSampleDurationMs = 0; 1266365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1267365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != mSttsTableEntries.end(); ++it) { 12688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t sampleDurationMs = 12698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000; 1270215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (sampleDurationMs > maxSampleDurationMs) { 1271215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong maxSampleDurationMs = sampleDurationMs; 1272215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong } else if (sampleDurationMs < minSampleDurationMs) { 1273215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong minSampleDurationMs = sampleDurationMs; 1274365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1275215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong LOGI("sample duration: %d ms", sampleDurationMs); 1276365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1277215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(minSampleDurationMs != 0); 1278215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(avgSampleDurationMs != 0); 1279215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(maxSampleDurationMs != 0); 1280215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong *min = minSampleDurationMs; 1281215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong *avg = avgSampleDurationMs; 1282215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong *max = maxSampleDurationMs; 1283365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1284365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1285365a963142093a1cd8efdcea76b5f65096a5b115James Dong// Don't count the last duration 1286365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) { 1287365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t duration = mOwner->interleaveDuration(); 1288365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t minChunkDuration = duration; 1289365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t maxChunkDuration = duration; 1290365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (mChunkDurations.size() > 1) { 1291365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<int64_t>::iterator it = mChunkDurations.begin(); 1292365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != --mChunkDurations.end(); ++it) { 1293365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (minChunkDuration > (*it)) { 1294365a963142093a1cd8efdcea76b5f65096a5b115James Dong minChunkDuration = (*it); 1295365a963142093a1cd8efdcea76b5f65096a5b115James Dong } else if (maxChunkDuration < (*it)) { 1296365a963142093a1cd8efdcea76b5f65096a5b115James Dong maxChunkDuration = (*it); 1297365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1298365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1299365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1300365a963142093a1cd8efdcea76b5f65096a5b115James Dong *min = minChunkDuration; 1301365a963142093a1cd8efdcea76b5f65096a5b115James Dong *max = maxChunkDuration; 1302365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1303365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1304365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::logStatisticalData(bool isAudio) { 1305365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (mMaxTimeStampUs <= 0 || mSampleInfos.empty()) { 1306365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("nothing is recorded"); 1307365a963142093a1cd8efdcea76b5f65096a5b115James Dong return; 1308365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1309365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1310365a963142093a1cd8efdcea76b5f65096a5b115James Dong bool collectStats = false; 1311365a963142093a1cd8efdcea76b5f65096a5b115James Dong char value[PROPERTY_VALUE_MAX]; 1312365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (property_get("media.stagefright.record-stats", value, NULL) 1313365a963142093a1cd8efdcea76b5f65096a5b115James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 1314365a963142093a1cd8efdcea76b5f65096a5b115James Dong collectStats = true; 1315365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1316365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1317365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (collectStats) { 1318215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong LOGI("%s track - duration %lld us, total %d frames", 1319215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong isAudio? "audio": "video", mMaxTimeStampUs, 1320215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong mSampleInfos.size()); 1321215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t min, avg, max; 1322215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong findMinAvgMaxSampleDurationMs(&min, &avg, &max); 1323215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max); 1324215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (!isAudio) { 1325215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong float avgFps = 1000.0 / avg; 1326215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong float minFps = 1000.0 / max; 1327215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong float maxFps = 1000.0 / min; 1328365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f", 1329215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong minFps, avgFps, maxFps); 1330365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1331365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1332365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t totalBytes = 0; 1333365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 1334365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != mSampleInfos.end(); ++it) { 1335365a963142093a1cd8efdcea76b5f65096a5b115James Dong totalBytes += it->size; 1336365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1337365a963142093a1cd8efdcea76b5f65096a5b115James Dong float bitRate = (totalBytes * 8000000.0) / mMaxTimeStampUs; 1338365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("avg bit rate (bps): %.2f", bitRate); 1339365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1340365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t duration = mOwner->interleaveDuration(); 1341365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (duration != 0) { // If interleaving is enabled 1342365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t minChunk, maxChunk; 1343365a963142093a1cd8efdcea76b5f65096a5b115James Dong findMinMaxChunkDurations(&minChunk, &maxChunk); 1344365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld", 1345365a963142093a1cd8efdcea76b5f65096a5b115James Dong minChunk, duration, maxChunk); 1346365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1347365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 134813aec890216948b0c364f8f92792129d0335f506James Dong} 134913aec890216948b0c364f8f92792129d0335f506James Dong 135013aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::Track::writeOneChunk(bool isAvc) { 135113aec890216948b0c364f8f92792129d0335f506James Dong mOwner->lock(); 135213aec890216948b0c364f8f92792129d0335f506James Dong for (List<MediaBuffer *>::iterator it = mChunkSamples.begin(); 135313aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkSamples.end(); ++it) { 135413aec890216948b0c364f8f92792129d0335f506James Dong off_t offset = isAvc? mOwner->addLengthPrefixedSample_l(*it) 135513aec890216948b0c364f8f92792129d0335f506James Dong : mOwner->addSample_l(*it); 135613aec890216948b0c364f8f92792129d0335f506James Dong if (it == mChunkSamples.begin()) { 135713aec890216948b0c364f8f92792129d0335f506James Dong mChunkOffsets.push_back(offset); 135813aec890216948b0c364f8f92792129d0335f506James Dong } 135913aec890216948b0c364f8f92792129d0335f506James Dong } 136013aec890216948b0c364f8f92792129d0335f506James Dong mOwner->unlock(); 136113aec890216948b0c364f8f92792129d0335f506James Dong while (!mChunkSamples.empty()) { 136213aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *>::iterator it = mChunkSamples.begin(); 136313aec890216948b0c364f8f92792129d0335f506James Dong (*it)->release(); 136413aec890216948b0c364f8f92792129d0335f506James Dong (*it) = NULL; 136513aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.erase(it); 136613aec890216948b0c364f8f92792129d0335f506James Dong } 136713aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13703b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 13713b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber return mMaxTimeStampUs; 137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1374d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 1375d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 1376d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1377d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 13781acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader( 13791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t trackID, bool use32BitOffset) { 138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 138120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findCString(kKeyMIMEType, &mime); 13820c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 138420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool is_audio = !strncasecmp(mime, "audio/", 6); 13858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("%s track time scale: %d", 13868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong is_audio? "Audio": "Video", mTimeScale); 13878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 13908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 13918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("trak"); 139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("tkhd"); 13961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Flags = 7 to indicate that the track is enabled, and 13971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // part of the presentation 13981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0x07); // version=0, flags=7 139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 140020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 140120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(trackID); 140220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 14038f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t tkhdDuration = 14048f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 14058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // layer 140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // alternate group 141020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(is_audio ? 0x100 : 0); // volume 141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 141220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); // matrix 141420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); 141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 141920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 142020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 142120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x40000000); 142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 142420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 142520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 142620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 142820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 14300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 143120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1432050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 1433050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 143520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // tkhd 143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1437f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 1438f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (mStartTimestampUs != moovStartTimeUs) { 14393c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("edts"); 14403c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("elst"); 14411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0); // version=0, flags=0: 32-bit time 14421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(2); // never ends with an empty list 14438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 14448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // First elst entry: specify the starting time offset 14458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t offsetUs = mStartTimestampUs - moovStartTimeUs; 14468f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6; 14478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(seg); // in mvhd timecale 14488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(-1); // starting time offset 14498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(1 << 16); // rate = 1.0 14508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 14518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // Second elst entry: specify the track duration 14528f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 14538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(seg); // in mvhd timescale 14541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0); 14551acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); 14563c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 14573c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 14583c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 14593c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 146020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdia"); 146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdhd"); 146320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 146420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 146520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 14668f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(mTimeScale); // media timescale 14678f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 14688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(mdhdDuration); // use media timescale 14691acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Language follows the three letter standard ISO-639-2/T 14701acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // 'e', 'n', 'g' for "English", for instance. 14711acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Each character is packed as the difference between its ASCII value and 0x60. 14721acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // For "English", these are 00101, 01110, 00111. 14731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // XXX: Where is the padding bit located: 0x15C7? 14741acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt16(0); // language code 147520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 147720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 147820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("hdlr"); 147920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1480050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // component type: should be mhlr 1481050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeFourcc(is_audio ? "soun" : "vide"); // component subtype 148220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 148320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 148420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 14851acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Removing "r" for the name string just makes the string 4 byte aligned 14861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeCString(is_audio ? "SoundHandle": "VideoHandle"); // name 148720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 148820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("minf"); 149020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("smhd"); 149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 149320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // balance 149420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 149520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 149620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 149720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("vmhd"); 14981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0x01); // version=0, flags=1 149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // graphics mode 150020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // opcolor 150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 150420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1505050b28a593350047845a45a14cc5026221ac1620James Dong 1506050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dinf"); 1507050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dref"); 1508050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 15091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1); // entry count (either url or urn) 15101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // The table index here refers to the sample description index 15111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // in the sample table entries. 1512050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("url "); 15131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 1514050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // url 1515050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dref 1516050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dinf 1517050b28a593350047845a45a14cc5026221ac1620James Dong 151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stbl"); 151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 152020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsd"); 152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); // entry count 152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 152425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber const char *fourcc = NULL; 152518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 152625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "samr"; 152718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 152825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "sawb"; 1529050b28a593350047845a45a14cc5026221ac1620James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1530050b28a593350047845a45a14cc5026221ac1620James Dong fourcc = "mp4a"; 153125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } else { 153225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 153325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber CHECK(!"should not be here, unknown mime type."); 153425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 153525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 153625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mOwner->beginBox(fourcc); // audio format 153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 1539050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x1); // data ref index 154020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 154120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 1542050b28a593350047845a45a14cc5026221ac1620James Dong int32_t nChannels; 1543050b28a593350047845a45a14cc5026221ac1620James Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 1544050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(nChannels); // channel count 154520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(16); // sample size 154620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 154720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 154820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 154920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t samplerate; 155020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 15510c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 155220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 155320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(samplerate << 16); 1554050b28a593350047845a45a14cc5026221ac1620James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1555050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("esds"); 1556050b28a593350047845a45a14cc5026221ac1620James Dong 1557050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1558050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x03); // ES_DescrTag 1559050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 1560050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x0000);// ES_ID 1561050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); 1562050b28a593350047845a45a14cc5026221ac1620James Dong 1563050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 1564050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 1565050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 1566050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x15); // streamType AudioStream 1567050b28a593350047845a45a14cc5026221ac1620James Dong 1568050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x03); // XXX 1569050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); // buffer size 24-bit 1570050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // max bit rate 1571050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // avg bit rate 1572050b28a593350047845a45a14cc5026221ac1620James Dong 1573050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 1574050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(mCodecSpecificDataSize); 1575050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 1576050b28a593350047845a45a14cc5026221ac1620James Dong 1577050b28a593350047845a45a14cc5026221ac1620James Dong static const uint8_t kData2[] = { 1578050b28a593350047845a45a14cc5026221ac1620James Dong 0x06, // SLConfigDescriptorTag 1579050b28a593350047845a45a14cc5026221ac1620James Dong 0x01, 1580050b28a593350047845a45a14cc5026221ac1620James Dong 0x02 1581050b28a593350047845a45a14cc5026221ac1620James Dong }; 1582050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(kData2, sizeof(kData2)); 1583050b28a593350047845a45a14cc5026221ac1620James Dong 1584050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // esds 1585050b28a593350047845a45a14cc5026221ac1620James Dong } 158620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 158720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 158818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 158920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mp4v"); 159018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 159120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("s263"); 159230ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 159330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avc1"); 159420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 159525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 15960c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!"should not be here, unknown mime type."); 159720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 159820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 159920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 160020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 16011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt16(1); // data ref index 160220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 160320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 160420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 160520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 160620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 160720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 160820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 160920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 161020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 16110c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 161220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 161320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(width); 161420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(height); 161520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // horiz resolution 161620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // vert resolution 161720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 161820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(1); // frame count 161920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(" ", 32); 162020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x18); // depth 162120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(-1); // predefined 162220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16230c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(23 + mCodecSpecificDataSize < 128); 162420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 162518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 162620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("esds"); 162720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 162820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x03); // ES_DescrTag 163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(23 + mCodecSpecificDataSize); 163220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x0000); // ES_ID 163320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x1f); 163420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 163520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x04); // DecoderConfigDescrTag 163620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(15 + mCodecSpecificDataSize); 163720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 163820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x11); // streamType VisualStream 163920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 164020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData[] = { 164120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 0x77, 0x00, 164220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00, 164320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00 164420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 164520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData, sizeof(kData)); 1646050b28a593350047845a45a14cc5026221ac1620James Dong 164720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 164820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 164920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(mCodecSpecificDataSize); 165020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 165120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 165220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData2[] = { 165320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x06, // SLConfigDescriptorTag 165420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 165520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x02 165620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 165720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData2, sizeof(kData2)); 165820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 165920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // esds 166018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 166120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("d263"); 166220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 166320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // vendor 166420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // decoder version 166520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(10); // level: 10 166620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // profile: 0 166720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 166820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // d263 166930ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 167030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avcC"); 167130ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 167230ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // avcC 167320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 167430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 16751acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->beginBox("pasp"); 16761acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // This is useful if the pixel is not square 16771acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // hspacing 16781acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // vspacing 16791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->endBox(); // pasp 168030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // mp4v, s263 or avc1 168120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 168220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsd 168320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 168420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stts"); 168520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1686be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(mSttsTableEntries.size()); 1687be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1688be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSttsTableEntries.end(); ++it) { 1689be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleCount); 16908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t dur = (it->sampleDurationUs * mTimeScale + 5E5) / 1E6; 16918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(dur); 169220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 169320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stts 169420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1695050b28a593350047845a45a14cc5026221ac1620James Dong if (!is_audio) { 1696050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("stss"); 1697050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1698050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames 1699050b28a593350047845a45a14cc5026221ac1620James Dong for (List<int32_t>::iterator it = mStssTableEntries.begin(); 1700050b28a593350047845a45a14cc5026221ac1620James Dong it != mStssTableEntries.end(); ++it) { 1701050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(*it); 1702050b28a593350047845a45a14cc5026221ac1620James Dong } 1703050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // stss 1704050b28a593350047845a45a14cc5026221ac1620James Dong } 1705050b28a593350047845a45a14cc5026221ac1620James Dong 170620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsz"); 170720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1708be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 1709be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SampleInfo>::iterator it = mSampleInfos.begin(); 1710be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->size); // default sample size 1711be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1712be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(0); 1713be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 171420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(mSampleInfos.size()); 1715be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (!mSamplesHaveSameSize) { 1716be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 1717be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSampleInfos.end(); ++it) { 1718be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32((*it).size); 1719be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 172020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 172120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsz 172220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 172320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsc"); 172420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 172513aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(mStscTableEntries.size()); 172613aec890216948b0c364f8f92792129d0335f506James Dong for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 172713aec890216948b0c364f8f92792129d0335f506James Dong it != mStscTableEntries.end(); ++it) { 172813aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->firstChunk); 172913aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->samplesPerChunk); 173013aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->sampleDescriptionId); 173120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 173220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsc 17331acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 173420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 173513aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(mChunkOffsets.size()); 173613aec890216948b0c364f8f92792129d0335f506James Dong for (List<off_t>::iterator it = mChunkOffsets.begin(); 173713aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkOffsets.end(); ++it) { 17381acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (use32BitOffset) { 17391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(static_cast<int32_t>(*it)); 17401acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 17411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt64((*it)); 17421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 174320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 17448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->endBox(); // stco or co64 174520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 174620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stbl 17471acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->endBox(); // minf 174820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // mdia 174920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // trak 175020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 175120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 175220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 1753