MPEG4Writer.cpp revision a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7f
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 3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 4125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track(MPEG4Writer *owner, const sp<MediaSource> &source); 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t start(); 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void stop(); 46a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong void pause(); 4725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 493b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 50d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void writeTrackHeader(int32_t trackID); 5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 56693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 58a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 59a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 603b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t mMaxTimeStampUs; 61d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber struct SampleInfo { 6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t size; 6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t timestamp; 6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 6913aec890216948b0c364f8f92792129d0335f506James Dong List<SampleInfo> mSampleInfos; 70be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong bool mSamplesHaveSameSize; 71be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 7213aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 7313aec890216948b0c364f8f92792129d0335f506James Dong List<off_t> mChunkOffsets; 7413aec890216948b0c364f8f92792129d0335f506James Dong 7513aec890216948b0c364f8f92792129d0335f506James Dong struct StscTableEntry { 7613aec890216948b0c364f8f92792129d0335f506James Dong 7713aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 7813aec890216948b0c364f8f92792129d0335f506James Dong : firstChunk(chunk), 7913aec890216948b0c364f8f92792129d0335f506James Dong samplesPerChunk(samples), 8013aec890216948b0c364f8f92792129d0335f506James Dong sampleDescriptionId(id) {} 8113aec890216948b0c364f8f92792129d0335f506James Dong 8213aec890216948b0c364f8f92792129d0335f506James Dong uint32_t firstChunk; 8313aec890216948b0c364f8f92792129d0335f506James Dong uint32_t samplesPerChunk; 8413aec890216948b0c364f8f92792129d0335f506James Dong uint32_t sampleDescriptionId; 8513aec890216948b0c364f8f92792129d0335f506James Dong }; 8613aec890216948b0c364f8f92792129d0335f506James Dong List<StscTableEntry> mStscTableEntries; 8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 88050b28a593350047845a45a14cc5026221ac1620James Dong List<int32_t> mStssTableEntries; 89365a963142093a1cd8efdcea76b5f65096a5b115James Dong List<int64_t> mChunkDurations; 90050b28a593350047845a45a14cc5026221ac1620James Dong 91be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong struct SttsTableEntry { 92be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 93be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong SttsTableEntry(uint32_t count, uint32_t duration) 94be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong : sampleCount(count), sampleDuration(duration) {} 95be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 96be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t sampleCount; 97be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t sampleDuration; 98be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong }; 99be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SttsTableEntry> mSttsTableEntries; 100be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 103548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 1063c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 10725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void threadEntry(); 11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t makeAVCCodecSpecificData( 11203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size); 11313aec890216948b0c364f8f92792129d0335f506James Dong void writeOneChunk(bool isAvc); 114365a963142093a1cd8efdcea76b5f65096a5b115James Dong void logStatisticalData(bool isAudio); 115365a963142093a1cd8efdcea76b5f65096a5b115James Dong void findMinMaxFrameRates(float *minFps, float *maxFps); 116365a963142093a1cd8efdcea76b5f65096a5b115James Dong void findMinMaxChunkDurations(int64_t *min, int64_t *max); 11703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR 1 12303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 12420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFile(fopen(filename, "wb")), 126a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 127a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 12913aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1307837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 13113aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs(500000) { 1320c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mFile != NULL); 13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 13420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13530ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 13630ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mFile(fdopen(fd, "wb")), 137a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 138a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 13930ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 14013aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1417837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 14213aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs(500000) { 14330ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(mFile != NULL); 14430ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 14530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 14620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1562dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 15725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track *track = new Track(this, source); 15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 1592dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 1602dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 163a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongstatus_t MPEG4Writer::startTracks() { 164a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 165a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 166a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong status_t err = (*it)->start(); 167a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 168a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 169a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 170a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 171a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 172a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 173a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 174a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 175a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 176a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 177a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 178a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 179a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 18025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::start() { 18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 18225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 185a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 186a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 187a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 188a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return startTracks(); 189a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 190a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 191a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 192a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1933c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mStartTimestampUs = 0; 1947837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = true; 1957837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 1967837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 1977837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 1987837c17063a4c50bc856ba59418516fdab731de7James Dong 19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("ftyp"); 20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); 20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2057837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2077837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 2087837c17063a4c50bc856ba59418516fdab731de7James Dong // XXX: Estimate the moov box size 2097837c17063a4c50bc856ba59418516fdab731de7James Dong // based on max file size or duration limit 2107837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize = 0x0F00; 2117837c17063a4c50bc856ba59418516fdab731de7James Dong } 2127837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mEstimatedMoovBoxSize >= 8); 2137837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 2147837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize); 2157837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 2167837c17063a4c50bc856ba59418516fdab731de7James Dong 2177837c17063a4c50bc856ba59418516fdab731de7James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 2187837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 2197837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 2207837c17063a4c50bc856ba59418516fdab731de7James Dong write("\x00\x00\x00\x01mdat????????", 16); 22125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 222a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong status_t err = startTracks(); 223a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 224a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 226a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 22725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 230a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::pause() { 231a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mFile == NULL) { 232a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return; 233a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 234a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 235a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 236a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 237a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it)->pause(); 238a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 239a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 240a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() { 24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t max_duration = 0; 24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->stop(); 25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2513b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t duration = (*it)->getDurationUs(); 25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (duration > max_duration) { 25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber max_duration = duration; 25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2577837c17063a4c50bc856ba59418516fdab731de7James Dong 25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 2597837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mMdatOffset + 8, SEEK_SET); 26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t size = mOffset - mMdatOffset; 26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size = hton64(size); 26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&size, 1, 8, mFile); 2637837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 2667837c17063a4c50bc856ba59418516fdab731de7James Dong const off_t moovOffset = mOffset; 2677837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = true; 2687837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 2697837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 2707837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("moov"); 27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("mvhd"); 27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // version=0, flags=0 27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // creation time 27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // modification time 27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(1000); // timescale 2793b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber writeInt32(max_duration / 1000); 28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // rate 28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0x100); // volume 28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0); // reserved 28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // matrix 28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); 29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x40000000); 29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mTracks.size() + 1); // nextTrackID 30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // mvhd 30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t id = 1; 30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it, ++id) { 30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->writeTrackHeader(id); 30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // moov 30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3107837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 3117837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 3127837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 3137837c17063a4c50bc856ba59418516fdab731de7James Dong 3147837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 3157837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 3167837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 3177837c17063a4c50bc856ba59418516fdab731de7James Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); 3187837c17063a4c50bc856ba59418516fdab731de7James Dong 3197837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 3207837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mStreamableFile? mOffset: mFreeBoxOffset; 3217837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 3227837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 3237837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 3247837c17063a4c50bc856ba59418516fdab731de7James Dong 3257837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 3267837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 3277837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 3287837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 3297837c17063a4c50bc856ba59418516fdab731de7James Dong } 3307837c17063a4c50bc856ba59418516fdab731de7James Dong 3310c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3337837c17063a4c50bc856ba59418516fdab731de7James Dong fflush(mFile); 33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fclose(mFile); 33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFile = NULL; 336a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = false; 33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33913aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 34013aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 34113aec890216948b0c364f8f92792129d0335f506James Dong return OK; 34213aec890216948b0c364f8f92792129d0335f506James Dong} 34313aec890216948b0c364f8f92792129d0335f506James Dong 34413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 34513aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 34613aec890216948b0c364f8f92792129d0335f506James Dong} 34713aec890216948b0c364f8f92792129d0335f506James Dong 34813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 34913aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 35013aec890216948b0c364f8f92792129d0335f506James Dong} 35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35213aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t old_offset = mOffset; 35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1, buffer->range_length(), mFile); 35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 36403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 36503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 36603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 36703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 36803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 36903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 37003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 37103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 37203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 37303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 37403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 37503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 37603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 37713aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 37830ab66297501757d745b9ae10da61adcd891f497Andreas Huber off_t old_offset = mOffset; 37930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 38030ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 38103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 38203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 38303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t x = length >> 24; 38403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 38503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 16) & 0xff; 38603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 38703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 8) & 0xff; 38803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 38903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = length & 0xff; 39003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 39103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 39230ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(length < 65536); 39330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 39430ab66297501757d745b9ae10da61adcd891f497Andreas Huber uint8_t x = length >> 8; 39530ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 39630ab66297501757d745b9ae10da61adcd891f497Andreas Huber x = length & 0xff; 39730ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 39803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 39930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 40030ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 40130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1, length, mFile); 40230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 40303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 40403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mOffset += length + 4; 40503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 40630ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset += length + 2; 40703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 40830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 40930ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 41030ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 41130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 4127837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 4137837c17063a4c50bc856ba59418516fdab731de7James Dong const void *ptr, size_t size, size_t nmemb, FILE *stream) { 4147837c17063a4c50bc856ba59418516fdab731de7James Dong 4157837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 4167837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 4177837c17063a4c50bc856ba59418516fdab731de7James Dong if (8 + mMoovBoxBufferOffset + bytes > mEstimatedMoovBoxSize) { 4187837c17063a4c50bc856ba59418516fdab731de7James Dong for (List<off_t>::iterator it = mBoxes.begin(); 4197837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 4207837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 4217837c17063a4c50bc856ba59418516fdab731de7James Dong } 4227837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 4237837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); 4247837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 4257837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 4267837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 4277837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 4287837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 4297837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 4307837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = false; 4317837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 4327837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 4337837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 4347837c17063a4c50bc856ba59418516fdab731de7James Dong } 4357837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 4367837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 4377837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 4387837c17063a4c50bc856ba59418516fdab731de7James Dong } 4397837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 4407837c17063a4c50bc856ba59418516fdab731de7James Dong} 4417837c17063a4c50bc856ba59418516fdab731de7James Dong 44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 4430c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4457837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 4467837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 4530c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset = *--mBoxes.end(); 45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4587837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 4597837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 4607837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 4617837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 4627837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, offset, SEEK_SET); 4637837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 4647837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 4657837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 4667837c17063a4c50bc856ba59418516fdab731de7James Dong } 46720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 46820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 4707837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 1, mFile); 47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 4757837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 2, mFile); 47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 47720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 4807837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 4, mFile); 48120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 48220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 48320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 4857837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 8, mFile); 48620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 48720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 48920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 4907837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, n + 1, mFile); 49120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 49220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 49320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 4940c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 4957837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, 4, mFile); 49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 49820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 4997837c17063a4c50bc856ba59418516fdab731de7James Dong write(data, 1, size, mFile); 50020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 50120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 502d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 503d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 504d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 505d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 506d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 507d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 508956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 509d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 510d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 511d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 512d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 513d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes); 514d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 515d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 516d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 517d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 518d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 519d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 520d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 521d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 522d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 523d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 524d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 525d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 526d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 527d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 528d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 529d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 530d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 53125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 53225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 53325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 53425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 53525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 53625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 53725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 53825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 53925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 54025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 54125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 54225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 54325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 5443c0131f02b6f008321608044c53bccce2ac5f6ddJames Dongvoid MPEG4Writer::setStartTimestamp(int64_t timeUs) { 5453c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong LOGI("setStartTimestamp: %lld", timeUs); 5463c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 5473c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong if (mStartTimestampUs != 0) { 5483c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return; // Sorry, too late 5493c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 5503c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mStartTimestampUs = timeUs; 5513c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 5523c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 5533c0131f02b6f008321608044c53bccce2ac5f6ddJames Dongint64_t MPEG4Writer::getStartTimestamp() { 5543c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong LOGI("getStartTimestamp: %lld", mStartTimestampUs); 5553c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 5563c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 5573c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 5583c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 56225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber MPEG4Writer *owner, const sp<MediaSource> &source) 56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 56425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 567a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 568a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 5693b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs(0), 570956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 571be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 57325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 574548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 57525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS(false) { 57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::Track::start() { 588a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 589a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 590a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 591a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 592a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 59325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t err = mSource->start(); 59425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 59525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 59625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 59725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 59825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 60120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 6053b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs = 0; 60625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 607956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 61020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 61125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 61225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 615a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::Track::pause() { 616a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 617a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 618a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() { 62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource->stop(); 63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 63225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 63325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 63425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 63525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 63920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track->threadEntry(); 64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 645548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h> 646548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) { 647548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber const uint8_t *data = (const uint8_t *)_data; 648548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t offset = 0; 649548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber while (offset < size) { 650548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("0x%04x ", offset); 651548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 652548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t n = size - offset; 653548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (n > 16) { 654548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber n = 16; 655548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 656548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 657548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < 16; ++i) { 658548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (i == 8) { 659548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 660548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 661548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 662548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (offset + i < size) { 663548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%02x ", data[offset + i]); 664548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 665548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 666548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 667548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 668548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 669548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 670548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 671548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < n; ++i) { 672548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (isprint(data[offset + i])) { 673548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%c", data[offset + i]); 674548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 675548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("."); 676548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 677548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 678548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 679548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("\n"); 680548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 681548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber offset += 16; 682548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 683548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber} 684548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 685548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 68603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 68703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 688548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber // hexdump(data, size); 689548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 69003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 691548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Already have codec specific data"); 69203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 69303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 69403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 69503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) { 696548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Must start with a start code"); 69703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 69803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 69903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 70003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamOffset = 4; 70103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber while (picParamOffset + 3 < size 70203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) { 70303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber ++picParamOffset; 70403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 70503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 70603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (picParamOffset + 3 >= size) { 707548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Could not find start-code for pictureParameterSet"); 70803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 70903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 71003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 71103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t seqParamSetLength = picParamOffset - 4; 71203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamSetLength = size - picParamOffset - 4; 71303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 71403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 71503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2; 71603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 71703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 71803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 71903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 72003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = 0x42; // profile 72103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = 0x80; 72203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[3] = 0x1e; // level 72303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 72403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 72503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 3; // length size == 4 bytes 72603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 72703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 1; // length size == 2 bytes 72803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 72903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 73003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[5] = 0xe0 | 1; 73103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[6] = seqParamSetLength >> 8; 73203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[7] = seqParamSetLength & 0xff; 73303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[8], &data[4], seqParamSetLength); 73403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header += 8 + seqParamSetLength; 73503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 73603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = picParamSetLength >> 8; 73703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = picParamSetLength & 0xff; 73803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength); 73903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 74003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 74103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 74203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() { 74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> meta = mSource->getFormat(); 74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber meta->findCString(kKeyMIMEType, &mime); 747050b28a593350047845a45a14cc5026221ac1620James Dong bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 748050b28a593350047845a45a14cc5026221ac1620James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 74930ab66297501757d745b9ae10da61adcd891f497Andreas Huber bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 750956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bool is_audio = !strncasecmp(mime, "audio/", 6); 75130ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 75213aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 75313aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 75413aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 75513aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 756be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong int64_t lastTimestamp = 0; // Timestamp of the previous sample 757be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong int64_t lastDuration = 0; // Time spacing between the previous two samples 758be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 759be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 760a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 761d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (!mDone && mSource->read(&buffer) == OK) { 76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 76813aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 772a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 773a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 774a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 775a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 776a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 777a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 778a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 779a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 780a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 78130ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 78230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 78303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 78403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 78503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 786548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 787548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 78803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (is_avc) { 78903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 79003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 79103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 79203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 793be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 79403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } else if (is_mpeg4) { 79503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 79603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 79703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 79803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 79903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 80003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 80130ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 80230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 80330ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 80430ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 80530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 806548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 80730ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 808548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && 809548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber count == 1 && is_mpeg4 && mCodecSpecificData == NULL) { 81003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI mpeg4 encoder does not properly set the 81103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // codec-specific-data flag. 81230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *data = 81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const size_t size = buffer->range_length(); 81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t offset = 0; 81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (offset + 3 < size) { 82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (data[offset] == 0x00 && data[offset + 1] == 0x00 82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) { 82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++offset; 82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8280c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber // CHECK(offset + 3 < size); 829bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber if (offset + 3 >= size) { 830bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // XXX assume the entire first chunk of data is the codec specific 831bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // data. 832bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber offset = size; 833bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber } 83420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 83520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificDataSize = offset; 83620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = malloc(offset); 83720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber memcpy(mCodecSpecificData, data, offset); 83820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->set_range(buffer->range_offset() + offset, size - offset); 84003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 84103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size == offset) { 84203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 84303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 84403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 84503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 84603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 847548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 848548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 849548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && is_avc && count < 3) { 85003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI video encoder does not flag codec specific data 85103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // as such and also splits up SPS and PPS across two buffers. 85203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 85303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data = 85403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 85503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 85603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t size = buffer->range_length(); 85703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 85803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber CHECK(count == 2 || mCodecSpecificData == NULL); 85903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 86003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t offset = mCodecSpecificDataSize; 86103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize += size + 4; 86203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = 86303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber realloc(mCodecSpecificData, mCodecSpecificDataSize); 86403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 86503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset, 86603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber "\x00\x00\x00\x01", 4); 86703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 86803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size); 86903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 87003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 87103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 87203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 87303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (count == 2) { 87403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber void *tmp = mCodecSpecificData; 87503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size = mCodecSpecificDataSize; 87603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = NULL; 87703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 0; 87803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 87903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 88003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)tmp, size); 88103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber free(tmp); 88203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber tmp = NULL; 883be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 884548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 885548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 88603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 88703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 88803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 88920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 89020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 891a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mGotAllCodecSpecificData) { 892a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mGotAllCodecSpecificData = true; 893a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 894a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 895d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 896d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 897d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 898d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 899d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 900d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 901d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 902d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 903d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 904d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 905d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (is_avc) StripStartcode(copy); 906e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber SampleInfo info; 90803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber info.size = is_avc 90903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 910d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong ? copy->range_length() + 4 91103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 912d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong ? copy->range_length() + 2 91303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 914d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong : copy->range_length(); 915050b28a593350047845a45a14cc5026221ac1620James Dong 916d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 917d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mEstimatedTrackSizeBytes += info.size; 918d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 919d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 920d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 921d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 922d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 923d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 924d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 925d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 926d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 927050b28a593350047845a45a14cc5026221ac1620James Dong 928d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 929d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 930d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 93148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int64_t timestampUs; 932d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 933d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 934d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 9353c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong if (mSampleInfos.empty()) { 9363c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->setStartTimestamp(timestampUs); 9373c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mStartTimestampUs = (timestampUs - mOwner->getStartTimestamp()); 9383c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 93948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 940a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 941a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - 1000 * lastDuration); 942a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 943a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 944a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 945a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 946a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong LOGV("time stamp: %lld and previous paused duration %lld", 947a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs, previousPausedDurationUs); 9483b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber if (timestampUs > mMaxTimeStampUs) { 9493b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs = timestampUs; 9503b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 9513b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 95248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber // Our timestamp is in ms. 95348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber info.timestamp = (timestampUs + 500) / 1000; 95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSampleInfos.push_back(info); 955be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() > 2) { 956be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (lastDuration != info.timestamp - lastTimestamp) { 957be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong SttsTableEntry sttsEntry(sampleCount, lastDuration); 958be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSttsTableEntries.push_back(sttsEntry); 959be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 960be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 961be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 962be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 963be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 964be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 965be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() >= 2 && previousSampleSize != info.size) { 966be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 967be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 968be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong previousSampleSize = info.size; 969be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 970be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong lastDuration = info.timestamp - lastTimestamp; 971be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong lastTimestamp = info.timestamp; 97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 973d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 974d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong mStssTableEntries.push_back(mSampleInfos.size()); 975d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 976d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 97713aec890216948b0c364f8f92792129d0335f506James Dong 97813aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 97913aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 98013aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(++nChunks, 1, 1); 98113aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 98213aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 98313aec890216948b0c364f8f92792129d0335f506James Dong } else { 98413aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 98513aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 98613aec890216948b0c364f8f92792129d0335f506James Dong } else { 98713aec890216948b0c364f8f92792129d0335f506James Dong if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 98813aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 989365a963142093a1cd8efdcea76b5f65096a5b115James Dong mChunkDurations.push_back(timestampUs - chunkTimestampUs); 99013aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 99113aec890216948b0c364f8f92792129d0335f506James Dong (--(mStscTableEntries.end()))->samplesPerChunk != 99213aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size()) { 99313aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(nChunks, 99413aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size(), 1); 99513aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 99613aec890216948b0c364f8f92792129d0335f506James Dong } 99713aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 99813aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 99913aec890216948b0c364f8f92792129d0335f506James Dong } 100013aec890216948b0c364f8f92792129d0335f506James Dong } 100113aec890216948b0c364f8f92792129d0335f506James Dong } 100213aec890216948b0c364f8f92792129d0335f506James Dong 100320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 100425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1005f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong if (mSampleInfos.empty()) { 1006f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_STOP_PREMATURELY, 0); 1007f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 1008be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 100913aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 101013aec890216948b0c364f8f92792129d0335f506James Dong if (!mChunkSamples.empty()) { 101113aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 101213aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1); 101313aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 101413aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 101513aec890216948b0c364f8f92792129d0335f506James Dong } 101613aec890216948b0c364f8f92792129d0335f506James Dong 1017be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 1018be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 1019be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 1020be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() == 1) { 1021be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong lastDuration = 0; // A single sample's duration 1022be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1023be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 1024be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1025be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong SttsTableEntry sttsEntry(sampleCount, lastDuration); 1026be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSttsTableEntries.push_back(sttsEntry); 102725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 1028956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s", 1029956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong count, nZeroLengthFrames, mSampleInfos.size(), is_audio? "audio": "video"); 1030365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1031365a963142093a1cd8efdcea76b5f65096a5b115James Dong logStatisticalData(is_audio); 1032365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1033365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1034365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::findMinMaxFrameRates(float *minFps, float *maxFps) { 1035365a963142093a1cd8efdcea76b5f65096a5b115James Dong int32_t minSampleDuration = 0x7FFFFFFF; 1036365a963142093a1cd8efdcea76b5f65096a5b115James Dong int32_t maxSampleDuration = 0; 1037365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1038365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != mSttsTableEntries.end(); ++it) { 1039365a963142093a1cd8efdcea76b5f65096a5b115James Dong int32_t sampleDuration = static_cast<int32_t>(it->sampleDuration); 1040365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (sampleDuration > maxSampleDuration) { 1041365a963142093a1cd8efdcea76b5f65096a5b115James Dong maxSampleDuration = sampleDuration; 1042365a963142093a1cd8efdcea76b5f65096a5b115James Dong } else if (sampleDuration < minSampleDuration) { 1043365a963142093a1cd8efdcea76b5f65096a5b115James Dong minSampleDuration = sampleDuration; 1044365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1045365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1046365a963142093a1cd8efdcea76b5f65096a5b115James Dong CHECK(minSampleDuration != 0 && maxSampleDuration != 0); 1047365a963142093a1cd8efdcea76b5f65096a5b115James Dong *minFps = 1000.0 / maxSampleDuration; 1048365a963142093a1cd8efdcea76b5f65096a5b115James Dong *maxFps = 1000.0 / minSampleDuration; 1049365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1050365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1051365a963142093a1cd8efdcea76b5f65096a5b115James Dong// Don't count the last duration 1052365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) { 1053365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t duration = mOwner->interleaveDuration(); 1054365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t minChunkDuration = duration; 1055365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t maxChunkDuration = duration; 1056365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (mChunkDurations.size() > 1) { 1057365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<int64_t>::iterator it = mChunkDurations.begin(); 1058365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != --mChunkDurations.end(); ++it) { 1059365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (minChunkDuration > (*it)) { 1060365a963142093a1cd8efdcea76b5f65096a5b115James Dong minChunkDuration = (*it); 1061365a963142093a1cd8efdcea76b5f65096a5b115James Dong } else if (maxChunkDuration < (*it)) { 1062365a963142093a1cd8efdcea76b5f65096a5b115James Dong maxChunkDuration = (*it); 1063365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1064365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1065365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1066365a963142093a1cd8efdcea76b5f65096a5b115James Dong *min = minChunkDuration; 1067365a963142093a1cd8efdcea76b5f65096a5b115James Dong *max = maxChunkDuration; 1068365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1069365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1070365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::logStatisticalData(bool isAudio) { 1071365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (mMaxTimeStampUs <= 0 || mSampleInfos.empty()) { 1072365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("nothing is recorded"); 1073365a963142093a1cd8efdcea76b5f65096a5b115James Dong return; 1074365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1075365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1076365a963142093a1cd8efdcea76b5f65096a5b115James Dong bool collectStats = false; 1077365a963142093a1cd8efdcea76b5f65096a5b115James Dong char value[PROPERTY_VALUE_MAX]; 1078365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (property_get("media.stagefright.record-stats", value, NULL) 1079365a963142093a1cd8efdcea76b5f65096a5b115James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 1080365a963142093a1cd8efdcea76b5f65096a5b115James Dong collectStats = true; 1081365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1082365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1083365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (collectStats) { 1084365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (isAudio) { 1085365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("audio track - duration %lld us", mMaxTimeStampUs); 1086365a963142093a1cd8efdcea76b5f65096a5b115James Dong } else { 1087365a963142093a1cd8efdcea76b5f65096a5b115James Dong float fps = (mSampleInfos.size() * 1000000.0) / mMaxTimeStampUs; 1088365a963142093a1cd8efdcea76b5f65096a5b115James Dong float minFps; 1089365a963142093a1cd8efdcea76b5f65096a5b115James Dong float maxFps; 1090365a963142093a1cd8efdcea76b5f65096a5b115James Dong findMinMaxFrameRates(&minFps, &maxFps); 1091365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("video track - duration %lld us", mMaxTimeStampUs); 1092365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f", 1093365a963142093a1cd8efdcea76b5f65096a5b115James Dong minFps, fps, maxFps); 1094365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1095365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1096365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t totalBytes = 0; 1097365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 1098365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != mSampleInfos.end(); ++it) { 1099365a963142093a1cd8efdcea76b5f65096a5b115James Dong totalBytes += it->size; 1100365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1101365a963142093a1cd8efdcea76b5f65096a5b115James Dong float bitRate = (totalBytes * 8000000.0) / mMaxTimeStampUs; 1102365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("avg bit rate (bps): %.2f", bitRate); 1103365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1104365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t duration = mOwner->interleaveDuration(); 1105365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (duration != 0) { // If interleaving is enabled 1106365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t minChunk, maxChunk; 1107365a963142093a1cd8efdcea76b5f65096a5b115James Dong findMinMaxChunkDurations(&minChunk, &maxChunk); 1108365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld", 1109365a963142093a1cd8efdcea76b5f65096a5b115James Dong minChunk, duration, maxChunk); 1110365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1111365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 111213aec890216948b0c364f8f92792129d0335f506James Dong} 111313aec890216948b0c364f8f92792129d0335f506James Dong 111413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::Track::writeOneChunk(bool isAvc) { 111513aec890216948b0c364f8f92792129d0335f506James Dong mOwner->lock(); 111613aec890216948b0c364f8f92792129d0335f506James Dong for (List<MediaBuffer *>::iterator it = mChunkSamples.begin(); 111713aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkSamples.end(); ++it) { 111813aec890216948b0c364f8f92792129d0335f506James Dong off_t offset = isAvc? mOwner->addLengthPrefixedSample_l(*it) 111913aec890216948b0c364f8f92792129d0335f506James Dong : mOwner->addSample_l(*it); 112013aec890216948b0c364f8f92792129d0335f506James Dong if (it == mChunkSamples.begin()) { 112113aec890216948b0c364f8f92792129d0335f506James Dong mChunkOffsets.push_back(offset); 112213aec890216948b0c364f8f92792129d0335f506James Dong } 112313aec890216948b0c364f8f92792129d0335f506James Dong } 112413aec890216948b0c364f8f92792129d0335f506James Dong mOwner->unlock(); 112513aec890216948b0c364f8f92792129d0335f506James Dong while (!mChunkSamples.empty()) { 112613aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *>::iterator it = mChunkSamples.begin(); 112713aec890216948b0c364f8f92792129d0335f506James Dong (*it)->release(); 112813aec890216948b0c364f8f92792129d0335f506James Dong (*it) = NULL; 112913aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.erase(it); 113013aec890216948b0c364f8f92792129d0335f506James Dong } 113113aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 113220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11343b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 11353b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber return mMaxTimeStampUs; 113620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 113720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1138d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 1139d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 1140d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1141d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 114220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { 114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 114420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findCString(kKeyMIMEType, &mime); 11450c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 114620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 114720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool is_audio = !strncasecmp(mime, "audio/", 6); 114820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 114920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 115020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("trak"); 115220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("tkhd"); 115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 115520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 115620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 115720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(trackID); 115820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 11593b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mOwner->writeInt32(getDurationUs() / 1000); 116020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 116220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // layer 116320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // alternate group 116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(is_audio ? 0x100 : 0); // volume 116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 116620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); // matrix 116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); 117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x40000000); 117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 11840c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1186050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 1187050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // tkhd 119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11913c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong if (mStartTimestampUs != 0) { 11923c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("edts"); 11933c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->writeInt32(0); // version=0, flags=0 11943c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("elst"); 11953c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->writeInt32(0); // version=0, flags=0 11963c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->writeInt32(1); // a single entry 11973c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->writeInt32(mStartTimestampUs / 1000); // edit duration 1198956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mOwner->writeInt32(-1); // empty edit box to signal starting time offset 11993c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->writeInt32(1); // x1 rate 12003c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 12013c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 12023c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 12033c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdia"); 120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdhd"); 120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 121020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1000); // timescale 12113b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mOwner->writeInt32(getDurationUs() / 1000); 121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // language code XXX 121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("hdlr"); 121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1218050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // component type: should be mhlr 1219050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeFourcc(is_audio ? "soun" : "vide"); // component subtype 122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 1223956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mOwner->writeCString(is_audio ? "SoundHandler": ""); // name 122420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("minf"); 122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("smhd"); 122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // balance 123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("vmhd"); 123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x00000001); // version=0, flags=1 123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // graphics mode 123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // opcolor 123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1242050b28a593350047845a45a14cc5026221ac1620James Dong 1243050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dinf"); 1244050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dref"); 1245050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1246050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(1); 1247050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("url "); 1248050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(1); // version=0, flags=1 1249050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // url 1250050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dref 1251050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dinf 1252050b28a593350047845a45a14cc5026221ac1620James Dong 1253050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // minf 125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stbl"); 125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsd"); 125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 125920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); // entry count 126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 126125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber const char *fourcc = NULL; 126218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 126325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "samr"; 126418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 126525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "sawb"; 1266050b28a593350047845a45a14cc5026221ac1620James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1267050b28a593350047845a45a14cc5026221ac1620James Dong fourcc = "mp4a"; 126825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } else { 126925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 127025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber CHECK(!"should not be here, unknown mime type."); 127125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 127225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 127325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mOwner->beginBox(fourcc); // audio format 127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 127520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 1276050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x1); // data ref index 127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 1279050b28a593350047845a45a14cc5026221ac1620James Dong int32_t nChannels; 1280050b28a593350047845a45a14cc5026221ac1620James Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 1281050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(nChannels); // channel count 128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(16); // sample size 128320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t samplerate; 128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 12880c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(samplerate << 16); 1291050b28a593350047845a45a14cc5026221ac1620James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1292050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("esds"); 1293050b28a593350047845a45a14cc5026221ac1620James Dong 1294050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1295050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x03); // ES_DescrTag 1296050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 1297050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x0000);// ES_ID 1298050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); 1299050b28a593350047845a45a14cc5026221ac1620James Dong 1300050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 1301050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 1302050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 1303050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x15); // streamType AudioStream 1304050b28a593350047845a45a14cc5026221ac1620James Dong 1305050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x03); // XXX 1306050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); // buffer size 24-bit 1307050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // max bit rate 1308050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // avg bit rate 1309050b28a593350047845a45a14cc5026221ac1620James Dong 1310050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 1311050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(mCodecSpecificDataSize); 1312050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 1313050b28a593350047845a45a14cc5026221ac1620James Dong 1314050b28a593350047845a45a14cc5026221ac1620James Dong static const uint8_t kData2[] = { 1315050b28a593350047845a45a14cc5026221ac1620James Dong 0x06, // SLConfigDescriptorTag 1316050b28a593350047845a45a14cc5026221ac1620James Dong 0x01, 1317050b28a593350047845a45a14cc5026221ac1620James Dong 0x02 1318050b28a593350047845a45a14cc5026221ac1620James Dong }; 1319050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(kData2, sizeof(kData2)); 1320050b28a593350047845a45a14cc5026221ac1620James Dong 1321050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // esds 1322050b28a593350047845a45a14cc5026221ac1620James Dong } 132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 132518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 132620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mp4v"); 132718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("s263"); 132930ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 133030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avc1"); 133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 133225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 13330c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!"should not be here, unknown mime type."); 133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // data ref index 133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 13480c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(width); 135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(height); 135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // horiz resolution 135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // vert resolution 135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(1); // frame count 135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(" ", 32); 135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x18); // depth 135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(-1); // predefined 135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13600c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(23 + mCodecSpecificDataSize < 128); 136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("esds"); 136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x03); // ES_DescrTag 136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(23 + mCodecSpecificDataSize); 136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x0000); // ES_ID 137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x1f); 137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x04); // DecoderConfigDescrTag 137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(15 + mCodecSpecificDataSize); 137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 137520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x11); // streamType VisualStream 137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData[] = { 137820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 0x77, 0x00, 137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00, 138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00 138120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData, sizeof(kData)); 1383050b28a593350047845a45a14cc5026221ac1620James Dong 138420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 138620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(mCodecSpecificDataSize); 138720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData2[] = { 139020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x06, // SLConfigDescriptorTag 139120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x02 139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData2, sizeof(kData2)); 139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // esds 139718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 139820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("d263"); 139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 140020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // vendor 140120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // decoder version 140220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(10); // level: 10 140320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // profile: 0 140420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // d263 140630ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 140730ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avcC"); 140830ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 140930ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // avcC 141020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 141130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 141230ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // mp4v, s263 or avc1 141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 141420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsd 141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stts"); 141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1418be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(mSttsTableEntries.size()); 1419be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1420be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSttsTableEntries.end(); ++it) { 1421be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleCount); 1422be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleDuration); 142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 142420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stts 142520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1426050b28a593350047845a45a14cc5026221ac1620James Dong if (!is_audio) { 1427050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("stss"); 1428050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1429050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames 1430050b28a593350047845a45a14cc5026221ac1620James Dong for (List<int32_t>::iterator it = mStssTableEntries.begin(); 1431050b28a593350047845a45a14cc5026221ac1620James Dong it != mStssTableEntries.end(); ++it) { 1432050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(*it); 1433050b28a593350047845a45a14cc5026221ac1620James Dong } 1434050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // stss 1435050b28a593350047845a45a14cc5026221ac1620James Dong } 1436050b28a593350047845a45a14cc5026221ac1620James Dong 143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsz"); 143820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1439be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 1440be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SampleInfo>::iterator it = mSampleInfos.begin(); 1441be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->size); // default sample size 1442be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1443be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(0); 1444be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(mSampleInfos.size()); 1446be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (!mSamplesHaveSameSize) { 1447be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 1448be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSampleInfos.end(); ++it) { 1449be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32((*it).size); 1450be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 145120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 145220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsz 145320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 145420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsc"); 145520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 145613aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(mStscTableEntries.size()); 145713aec890216948b0c364f8f92792129d0335f506James Dong for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 145813aec890216948b0c364f8f92792129d0335f506James Dong it != mStscTableEntries.end(); ++it) { 145913aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->firstChunk); 146013aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->samplesPerChunk); 146113aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->sampleDescriptionId); 146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 146320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsc 146420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 146520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("co64"); 146620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 146713aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(mChunkOffsets.size()); 146813aec890216948b0c364f8f92792129d0335f506James Dong for (List<off_t>::iterator it = mChunkOffsets.begin(); 146913aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkOffsets.end(); ++it) { 147013aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt64((*it)); 147120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 147220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // co64 147320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 147420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stbl 147520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // mdia 147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // trak 147720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 147820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 147920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 1480