MPEG4Writer.cpp revision d599cd4573b5a2d5914c5040e0565ef866749b77
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> 3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 4025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track(MPEG4Writer *owner, const sp<MediaSource> &source); 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t start(); 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void stop(); 4525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 473b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 48d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void writeTrackHeader(int32_t trackID); 5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 54693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 563b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t mMaxTimeStampUs; 57d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber struct SampleInfo { 6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t size; 6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t timestamp; 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 6513aec890216948b0c364f8f92792129d0335f506James Dong List<SampleInfo> mSampleInfos; 66be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong bool mSamplesHaveSameSize; 67be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 6813aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 6913aec890216948b0c364f8f92792129d0335f506James Dong List<off_t> mChunkOffsets; 7013aec890216948b0c364f8f92792129d0335f506James Dong 7113aec890216948b0c364f8f92792129d0335f506James Dong struct StscTableEntry { 7213aec890216948b0c364f8f92792129d0335f506James Dong 7313aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 7413aec890216948b0c364f8f92792129d0335f506James Dong : firstChunk(chunk), 7513aec890216948b0c364f8f92792129d0335f506James Dong samplesPerChunk(samples), 7613aec890216948b0c364f8f92792129d0335f506James Dong sampleDescriptionId(id) {} 7713aec890216948b0c364f8f92792129d0335f506James Dong 7813aec890216948b0c364f8f92792129d0335f506James Dong uint32_t firstChunk; 7913aec890216948b0c364f8f92792129d0335f506James Dong uint32_t samplesPerChunk; 8013aec890216948b0c364f8f92792129d0335f506James Dong uint32_t sampleDescriptionId; 8113aec890216948b0c364f8f92792129d0335f506James Dong }; 8213aec890216948b0c364f8f92792129d0335f506James Dong List<StscTableEntry> mStscTableEntries; 8320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 84050b28a593350047845a45a14cc5026221ac1620James Dong List<int32_t> mStssTableEntries; 85050b28a593350047845a45a14cc5026221ac1620James Dong 86be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong struct SttsTableEntry { 87be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 88be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong SttsTableEntry(uint32_t count, uint32_t duration) 89be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong : sampleCount(count), sampleDuration(duration) {} 90be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 91be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t sampleCount; 92be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t sampleDuration; 93be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong }; 94be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SttsTableEntry> mSttsTableEntries; 95be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 98548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 10125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void threadEntry(); 10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t makeAVCCodecSpecificData( 10603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size); 10713aec890216948b0c364f8f92792129d0335f506James Dong void writeOneChunk(bool isAvc); 10803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR 1 11403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 11520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFile(fopen(filename, "wb")), 11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 11813aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1197837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 12013aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs(500000) { 1210c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mFile != NULL); 12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12430ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 12530ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mFile(fdopen(fd, "wb")), 12630ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 12713aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1287837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 12913aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs(500000) { 13030ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(mFile != NULL); 13130ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 13230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 13320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 13420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1432dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 14425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track *track = new Track(this, source); 14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 1462dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 1472dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::start() { 15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 15225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1557837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = true; 1567837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 1577837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 1587837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 1597837c17063a4c50bc856ba59418516fdab731de7James Dong 16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("ftyp"); 16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); 16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1667837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1687837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 1697837c17063a4c50bc856ba59418516fdab731de7James Dong // XXX: Estimate the moov box size 1707837c17063a4c50bc856ba59418516fdab731de7James Dong // based on max file size or duration limit 1717837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize = 0x0F00; 1727837c17063a4c50bc856ba59418516fdab731de7James Dong } 1737837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mEstimatedMoovBoxSize >= 8); 1747837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 1757837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize); 1767837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 1777837c17063a4c50bc856ba59418516fdab731de7James Dong 1787837c17063a4c50bc856ba59418516fdab731de7James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 1797837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 1807837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 1817837c17063a4c50bc856ba59418516fdab731de7James Dong write("\x00\x00\x00\x01mdat????????", 16); 18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 18425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t err = (*it)->start(); 18525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 18625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 18725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it2 = mTracks.begin(); 18825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it2 != it; ++it2) { 18925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber (*it2)->stop(); 19025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 19125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 19225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 19325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 19525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 19625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() { 20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t max_duration = 0; 20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->stop(); 20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2093b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t duration = (*it)->getDurationUs(); 21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (duration > max_duration) { 21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber max_duration = duration; 21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2157837c17063a4c50bc856ba59418516fdab731de7James Dong 21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 2177837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mMdatOffset + 8, SEEK_SET); 21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t size = mOffset - mMdatOffset; 21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size = hton64(size); 22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&size, 1, 8, mFile); 2217837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 2247837c17063a4c50bc856ba59418516fdab731de7James Dong const off_t moovOffset = mOffset; 2257837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = true; 2267837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 2277837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 2287837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("moov"); 23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("mvhd"); 23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // version=0, flags=0 23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // creation time 23520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // modification time 23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(1000); // timescale 2373b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber writeInt32(max_duration / 1000); 23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // rate 23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0x100); // volume 24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0); // reserved 24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // matrix 24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); 24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x40000000); 25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mTracks.size() + 1); // nextTrackID 25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // mvhd 26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t id = 1; 26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it, ++id) { 26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->writeTrackHeader(id); 26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // moov 26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2687837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 2697837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 2707837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 2717837c17063a4c50bc856ba59418516fdab731de7James Dong 2727837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 2737837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 2747837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 2757837c17063a4c50bc856ba59418516fdab731de7James Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); 2767837c17063a4c50bc856ba59418516fdab731de7James Dong 2777837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 2787837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mStreamableFile? mOffset: mFreeBoxOffset; 2797837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 2807837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 2817837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 2827837c17063a4c50bc856ba59418516fdab731de7James Dong 2837837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 2847837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 2857837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 2867837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 2877837c17063a4c50bc856ba59418516fdab731de7James Dong } 2887837c17063a4c50bc856ba59418516fdab731de7James Dong 2890c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2917837c17063a4c50bc856ba59418516fdab731de7James Dong fflush(mFile); 29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fclose(mFile); 29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFile = NULL; 29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29613aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 29713aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 29813aec890216948b0c364f8f92792129d0335f506James Dong return OK; 29913aec890216948b0c364f8f92792129d0335f506James Dong} 30013aec890216948b0c364f8f92792129d0335f506James Dong 30113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 30213aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 30313aec890216948b0c364f8f92792129d0335f506James Dong} 30413aec890216948b0c364f8f92792129d0335f506James Dong 30513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 30613aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 30713aec890216948b0c364f8f92792129d0335f506James Dong} 30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30913aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t old_offset = mOffset; 31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1, buffer->range_length(), mFile); 31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 32103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 32203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 32303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 32403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 32503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 32603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 32703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 32803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 32903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 33003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 33103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 33203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 33303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 33413aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 33503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber StripStartcode(buffer); 33603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 33730ab66297501757d745b9ae10da61adcd891f497Andreas Huber off_t old_offset = mOffset; 33830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 33930ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 34003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 34103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 34203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t x = length >> 24; 34303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 34403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 16) & 0xff; 34503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 34603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 8) & 0xff; 34703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 34803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = length & 0xff; 34903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 35003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 35130ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(length < 65536); 35230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 35330ab66297501757d745b9ae10da61adcd891f497Andreas Huber uint8_t x = length >> 8; 35430ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 35530ab66297501757d745b9ae10da61adcd891f497Andreas Huber x = length & 0xff; 35630ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 35703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 35830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 35930ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 36030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1, length, mFile); 36130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 36203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 36303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mOffset += length + 4; 36403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 36530ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset += length + 2; 36603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 36730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 36830ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 36930ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 37030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 3717837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 3727837c17063a4c50bc856ba59418516fdab731de7James Dong const void *ptr, size_t size, size_t nmemb, FILE *stream) { 3737837c17063a4c50bc856ba59418516fdab731de7James Dong 3747837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 3757837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 3767837c17063a4c50bc856ba59418516fdab731de7James Dong if (8 + mMoovBoxBufferOffset + bytes > mEstimatedMoovBoxSize) { 3777837c17063a4c50bc856ba59418516fdab731de7James Dong for (List<off_t>::iterator it = mBoxes.begin(); 3787837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 3797837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 3807837c17063a4c50bc856ba59418516fdab731de7James Dong } 3817837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 3827837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); 3837837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 3847837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 3857837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 3867837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 3877837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 3887837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 3897837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = false; 3907837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 3917837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 3927837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 3937837c17063a4c50bc856ba59418516fdab731de7James Dong } 3947837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 3957837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 3967837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 3977837c17063a4c50bc856ba59418516fdab731de7James Dong } 3987837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 3997837c17063a4c50bc856ba59418516fdab731de7James Dong} 4007837c17063a4c50bc856ba59418516fdab731de7James Dong 40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 4020c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4047837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 4057837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 4120c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset = *--mBoxes.end(); 41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4177837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 4187837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 4197837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 4207837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 4217837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, offset, SEEK_SET); 4227837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 4237837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 4247837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 4257837c17063a4c50bc856ba59418516fdab731de7James Dong } 42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 4297837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 1, mFile); 43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 4347837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 2, mFile); 43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 4397837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 4, mFile); 44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 4447837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 8, mFile); 44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 4497837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, n + 1, mFile); 45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 4530c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 4547837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, 4, mFile); 45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 4587837c17063a4c50bc856ba59418516fdab731de7James Dong write(data, 1, size, mFile); 45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 461d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 462d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 463d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 464d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 465d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 466d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 467d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t nTotalBytesEstimate = mEstimatedMoovBoxSize; 468d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 469d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 470d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 471d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 472d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes); 473d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 474d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 475d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 476d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 477d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 478d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 479d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 480d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 481d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 482d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 483d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 484d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 485d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 486d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 487d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 488d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 489d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 49025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 49125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 49225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 49325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 49425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 49525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 49625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 49725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 49825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 49925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 50025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 50125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 50225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 50320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 50420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 50520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 50625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber MPEG4Writer *owner, const sp<MediaSource> &source) 50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 50825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 5113b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs(0), 512be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 51425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 515548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 51625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS(false) { 51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 51920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 52825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::Track::start() { 52925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t err = mSource->start(); 53025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 53125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 53225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 53325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 53425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 5413b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs = 0; 54225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 54425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 54625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 54725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() { 55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource->stop(); 56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 56425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 56525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 56625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track->threadEntry(); 57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 576548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h> 577548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) { 578548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber const uint8_t *data = (const uint8_t *)_data; 579548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t offset = 0; 580548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber while (offset < size) { 581548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("0x%04x ", offset); 582548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 583548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t n = size - offset; 584548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (n > 16) { 585548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber n = 16; 586548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 587548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 588548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < 16; ++i) { 589548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (i == 8) { 590548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 591548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 592548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 593548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (offset + i < size) { 594548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%02x ", data[offset + i]); 595548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 596548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 597548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 598548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 599548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 600548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 601548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 602548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < n; ++i) { 603548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (isprint(data[offset + i])) { 604548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%c", data[offset + i]); 605548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 606548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("."); 607548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 608548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 609548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 610548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("\n"); 611548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 612548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber offset += 16; 613548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 614548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber} 615548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 616548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 61703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 61803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 619548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber // hexdump(data, size); 620548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 62103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 622548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Already have codec specific data"); 62303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 62403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 62503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 62603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) { 627548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Must start with a start code"); 62803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 62903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 63003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 63103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamOffset = 4; 63203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber while (picParamOffset + 3 < size 63303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) { 63403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber ++picParamOffset; 63503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 63603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 63703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (picParamOffset + 3 >= size) { 638548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Could not find start-code for pictureParameterSet"); 63903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 64003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 64103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 64203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t seqParamSetLength = picParamOffset - 4; 64303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamSetLength = size - picParamOffset - 4; 64403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 64503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 64603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2; 64703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 64803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 64903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 65003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 65103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = 0x42; // profile 65203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = 0x80; 65303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[3] = 0x1e; // level 65403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 65503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 65603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 3; // length size == 4 bytes 65703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 65803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 1; // length size == 2 bytes 65903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 66003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 66103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[5] = 0xe0 | 1; 66203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[6] = seqParamSetLength >> 8; 66303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[7] = seqParamSetLength & 0xff; 66403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[8], &data[4], seqParamSetLength); 66503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header += 8 + seqParamSetLength; 66603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 66703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = picParamSetLength >> 8; 66803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = picParamSetLength & 0xff; 66903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength); 67003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 67103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 67203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 67303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 67420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() { 67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> meta = mSource->getFormat(); 67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber meta->findCString(kKeyMIMEType, &mime); 678050b28a593350047845a45a14cc5026221ac1620James Dong bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 679050b28a593350047845a45a14cc5026221ac1620James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 68030ab66297501757d745b9ae10da61adcd891f497Andreas Huber bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 68130ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 68213aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 68313aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 68413aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 68513aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 686be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong int64_t lastTimestamp = 0; // Timestamp of the previous sample 687be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong int64_t lastDuration = 0; // Time spacing between the previous two samples 688be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 689be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 691d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mEstimatedTrackSizeBytes = 0; 69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 69320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (!mDone && mSource->read(&buffer) == OK) { 69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 69520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 69620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 69713aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 69920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 70130ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 70230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 70303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 70403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 70503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 706548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 707548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 70803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (is_avc) { 70903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 71003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 71103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 71203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 713be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 71403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } else if (is_mpeg4) { 71503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 71603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 71703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 71803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 71903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 72003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 72130ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 72230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 72330ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 72430ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 72530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 726548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 72730ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 728548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && 729548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber count == 1 && is_mpeg4 && mCodecSpecificData == NULL) { 73003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI mpeg4 encoder does not properly set the 73103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // codec-specific-data flag. 73230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *data = 73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const size_t size = buffer->range_length(); 73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t offset = 0; 73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (offset + 3 < size) { 74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (data[offset] == 0x00 && data[offset + 1] == 0x00 74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) { 74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++offset; 74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7480c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber // CHECK(offset + 3 < size); 749bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber if (offset + 3 >= size) { 750bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // XXX assume the entire first chunk of data is the codec specific 751bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // data. 752bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber offset = size; 753bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber } 75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificDataSize = offset; 75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = malloc(offset); 75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber memcpy(mCodecSpecificData, data, offset); 75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->set_range(buffer->range_offset() + offset, size - offset); 76003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 76103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size == offset) { 76203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 76303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 76403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 76503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 76603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 767548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 768548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 769548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && is_avc && count < 3) { 77003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI video encoder does not flag codec specific data 77103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // as such and also splits up SPS and PPS across two buffers. 77203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 77303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data = 77403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 77503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 77603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t size = buffer->range_length(); 77703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 77803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber CHECK(count == 2 || mCodecSpecificData == NULL); 77903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 78003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t offset = mCodecSpecificDataSize; 78103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize += size + 4; 78203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = 78303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber realloc(mCodecSpecificData, mCodecSpecificDataSize); 78403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 78503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset, 78603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber "\x00\x00\x00\x01", 4); 78703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 78803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size); 78903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 79003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 79103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 79203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 79303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (count == 2) { 79403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber void *tmp = mCodecSpecificData; 79503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size = mCodecSpecificDataSize; 79603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = NULL; 79703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 0; 79803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 79903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 80003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)tmp, size); 80103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber free(tmp); 80203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber tmp = NULL; 803be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 804548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 805548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 80603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 80703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 80803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber SampleInfo info; 81203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber info.size = is_avc 81303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 81413aec890216948b0c364f8f92792129d0335f506James Dong ? buffer->range_length() + 4 81503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 81613aec890216948b0c364f8f92792129d0335f506James Dong ? buffer->range_length() + 2 81703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 81813aec890216948b0c364f8f92792129d0335f506James Dong : buffer->range_length(); 819050b28a593350047845a45a14cc5026221ac1620James Dong 820d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 821d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mEstimatedTrackSizeBytes += info.size; 822d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 823d599cd4573b5a2d5914c5040e0565ef866749b77James Dong buffer->release(); 824d599cd4573b5a2d5914c5040e0565ef866749b77James Dong buffer = NULL; 825d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 826d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 827d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 828d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 829d599cd4573b5a2d5914c5040e0565ef866749b77James Dong buffer->release(); 830d599cd4573b5a2d5914c5040e0565ef866749b77James Dong buffer = NULL; 831d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 832d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 833d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 834d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 835050b28a593350047845a45a14cc5026221ac1620James Dong bool is_audio = !strncasecmp(mime, "audio/", 6); 836050b28a593350047845a45a14cc5026221ac1620James Dong 83748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int64_t timestampUs; 83848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); 83948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 8403b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber if (timestampUs > mMaxTimeStampUs) { 8413b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs = timestampUs; 8423b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 8433b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 84448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber // Our timestamp is in ms. 84548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber info.timestamp = (timestampUs + 500) / 1000; 84620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSampleInfos.push_back(info); 847be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() > 2) { 848be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (lastDuration != info.timestamp - lastTimestamp) { 849be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong SttsTableEntry sttsEntry(sampleCount, lastDuration); 850be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSttsTableEntries.push_back(sttsEntry); 851be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 852be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 853be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 854be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 855be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 856be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 857be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() >= 2 && previousSampleSize != info.size) { 858be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 859be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 860be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong previousSampleSize = info.size; 861be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 862be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong lastDuration = info.timestamp - lastTimestamp; 863be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong lastTimestamp = info.timestamp; 86420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 86513aec890216948b0c364f8f92792129d0335f506James Dong//////////////////////////////////////////////////////////////////////////////// 86613aec890216948b0c364f8f92792129d0335f506James Dong // Make a deep copy of the MediaBuffer less Metadata 86713aec890216948b0c364f8f92792129d0335f506James Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 86813aec890216948b0c364f8f92792129d0335f506James Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 86913aec890216948b0c364f8f92792129d0335f506James Dong buffer->range_length()); 87013aec890216948b0c364f8f92792129d0335f506James Dong copy->set_range(0, buffer->range_length()); 87113aec890216948b0c364f8f92792129d0335f506James Dong 87213aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 87313aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 87413aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(++nChunks, 1, 1); 87513aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 87613aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 87713aec890216948b0c364f8f92792129d0335f506James Dong } else { 87813aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 87913aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 88013aec890216948b0c364f8f92792129d0335f506James Dong } else { 88113aec890216948b0c364f8f92792129d0335f506James Dong if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 88213aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 88313aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 88413aec890216948b0c364f8f92792129d0335f506James Dong (--(mStscTableEntries.end()))->samplesPerChunk != 88513aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size()) { 88613aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(nChunks, 88713aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size(), 1); 88813aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 88913aec890216948b0c364f8f92792129d0335f506James Dong } 89013aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 89113aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 89213aec890216948b0c364f8f92792129d0335f506James Dong } 89313aec890216948b0c364f8f92792129d0335f506James Dong } 89413aec890216948b0c364f8f92792129d0335f506James Dong } 89513aec890216948b0c364f8f92792129d0335f506James Dong 896050b28a593350047845a45a14cc5026221ac1620James Dong int32_t isSync = false; 89713aec890216948b0c364f8f92792129d0335f506James Dong if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync) && 89813aec890216948b0c364f8f92792129d0335f506James Dong isSync != 0) { 899050b28a593350047845a45a14cc5026221ac1620James Dong mStssTableEntries.push_back(mSampleInfos.size()); 900050b28a593350047845a45a14cc5026221ac1620James Dong } 901be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 90220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 90320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 90525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 906be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK(!mSampleInfos.empty()); 907be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 90813aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 90913aec890216948b0c364f8f92792129d0335f506James Dong if (!mChunkSamples.empty()) { 91013aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 91113aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1); 91213aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 91313aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 91413aec890216948b0c364f8f92792129d0335f506James Dong } 91513aec890216948b0c364f8f92792129d0335f506James Dong 916be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 917be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 918be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 919be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() == 1) { 920be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong lastDuration = 0; // A single sample's duration 921be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 922be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 923be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 924be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong SttsTableEntry sttsEntry(sampleCount, lastDuration); 925be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSttsTableEntries.push_back(sttsEntry); 92625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 92713aec890216948b0c364f8f92792129d0335f506James Dong LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames", 92813aec890216948b0c364f8f92792129d0335f506James Dong count, nZeroLengthFrames, mSampleInfos.size()); 92913aec890216948b0c364f8f92792129d0335f506James Dong} 93013aec890216948b0c364f8f92792129d0335f506James Dong 93113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::Track::writeOneChunk(bool isAvc) { 93213aec890216948b0c364f8f92792129d0335f506James Dong mOwner->lock(); 93313aec890216948b0c364f8f92792129d0335f506James Dong for (List<MediaBuffer *>::iterator it = mChunkSamples.begin(); 93413aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkSamples.end(); ++it) { 93513aec890216948b0c364f8f92792129d0335f506James Dong off_t offset = isAvc? mOwner->addLengthPrefixedSample_l(*it) 93613aec890216948b0c364f8f92792129d0335f506James Dong : mOwner->addSample_l(*it); 93713aec890216948b0c364f8f92792129d0335f506James Dong if (it == mChunkSamples.begin()) { 93813aec890216948b0c364f8f92792129d0335f506James Dong mChunkOffsets.push_back(offset); 93913aec890216948b0c364f8f92792129d0335f506James Dong } 94013aec890216948b0c364f8f92792129d0335f506James Dong } 94113aec890216948b0c364f8f92792129d0335f506James Dong mOwner->unlock(); 94213aec890216948b0c364f8f92792129d0335f506James Dong while (!mChunkSamples.empty()) { 94313aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *>::iterator it = mChunkSamples.begin(); 94413aec890216948b0c364f8f92792129d0335f506James Dong (*it)->release(); 94513aec890216948b0c364f8f92792129d0335f506James Dong (*it) = NULL; 94613aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.erase(it); 94713aec890216948b0c364f8f92792129d0335f506James Dong } 94813aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9513b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 9523b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber return mMaxTimeStampUs; 95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 955d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 956d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 957d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 958d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { 96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 96120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findCString(kKeyMIMEType, &mime); 9620c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 96420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool is_audio = !strncasecmp(mime, "audio/", 6); 96520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 96620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 96720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 96820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("trak"); 96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 97020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("tkhd"); 97120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 97320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 97420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(trackID); 97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 9763b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mOwner->writeInt32(getDurationUs() / 1000); 97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // layer 98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // alternate group 98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(is_audio ? 0x100 : 0); // volume 98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); // matrix 98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 98820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); 98920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 99020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 99120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 99220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x40000000); 99320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 99420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 99620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 99720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 99820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 99920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 100020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 10010c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 100220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1003050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 1004050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 100520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 100620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // tkhd 100720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 100820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdia"); 100920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 101020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdhd"); 101120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 101220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 101320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 101420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1000); // timescale 10153b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mOwner->writeInt32(getDurationUs() / 1000); 101620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // language code XXX 101720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 101920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 102020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("hdlr"); 102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1022050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // component type: should be mhlr 1023050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeFourcc(is_audio ? "soun" : "vide"); // component subtype 102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 1027050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeCString("SoundHandler"); // name 102820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 102920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("minf"); 103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("smhd"); 103320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 103420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // balance 103520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 103620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 103720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 103820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("vmhd"); 103920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x00000001); // version=0, flags=1 104020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // graphics mode 104120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // opcolor 104220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 104320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 104420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1046050b28a593350047845a45a14cc5026221ac1620James Dong 1047050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dinf"); 1048050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dref"); 1049050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1050050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(1); 1051050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("url "); 1052050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(1); // version=0, flags=1 1053050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // url 1054050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dref 1055050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dinf 1056050b28a593350047845a45a14cc5026221ac1620James Dong 1057050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // minf 105820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 105920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stbl"); 106020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsd"); 106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 106320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); // entry count 106420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 106525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber const char *fourcc = NULL; 106618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 106725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "samr"; 106818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 106925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "sawb"; 1070050b28a593350047845a45a14cc5026221ac1620James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1071050b28a593350047845a45a14cc5026221ac1620James Dong fourcc = "mp4a"; 107225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } else { 107325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 107425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber CHECK(!"should not be here, unknown mime type."); 107525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 107625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 107725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mOwner->beginBox(fourcc); // audio format 107820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 107920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 1080050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x1); // data ref index 108120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 108220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 1083050b28a593350047845a45a14cc5026221ac1620James Dong int32_t nChannels; 1084050b28a593350047845a45a14cc5026221ac1620James Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 1085050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(nChannels); // channel count 108620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(16); // sample size 108720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 108820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 108920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 109020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t samplerate; 109120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 10920c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 109320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 109420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(samplerate << 16); 1095050b28a593350047845a45a14cc5026221ac1620James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1096050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("esds"); 1097050b28a593350047845a45a14cc5026221ac1620James Dong 1098050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1099050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x03); // ES_DescrTag 1100050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 1101050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x0000);// ES_ID 1102050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); 1103050b28a593350047845a45a14cc5026221ac1620James Dong 1104050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 1105050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 1106050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 1107050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x15); // streamType AudioStream 1108050b28a593350047845a45a14cc5026221ac1620James Dong 1109050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x03); // XXX 1110050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); // buffer size 24-bit 1111050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // max bit rate 1112050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // avg bit rate 1113050b28a593350047845a45a14cc5026221ac1620James Dong 1114050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 1115050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(mCodecSpecificDataSize); 1116050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 1117050b28a593350047845a45a14cc5026221ac1620James Dong 1118050b28a593350047845a45a14cc5026221ac1620James Dong static const uint8_t kData2[] = { 1119050b28a593350047845a45a14cc5026221ac1620James Dong 0x06, // SLConfigDescriptorTag 1120050b28a593350047845a45a14cc5026221ac1620James Dong 0x01, 1121050b28a593350047845a45a14cc5026221ac1620James Dong 0x02 1122050b28a593350047845a45a14cc5026221ac1620James Dong }; 1123050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(kData2, sizeof(kData2)); 1124050b28a593350047845a45a14cc5026221ac1620James Dong 1125050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // esds 1126050b28a593350047845a45a14cc5026221ac1620James Dong } 112720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 112918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 113020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mp4v"); 113118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 113220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("s263"); 113330ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 113430ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avc1"); 113520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 113625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 11370c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!"should not be here, unknown mime type."); 113820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 113920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 114020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 114120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 114220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // data ref index 114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 114420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 114520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 114620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 114720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 114820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 114920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 115020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 115120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 11520c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 115320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(width); 115520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(height); 115620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // horiz resolution 115720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // vert resolution 115820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 115920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(1); // frame count 116020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(" ", 32); 116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x18); // depth 116220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(-1); // predefined 116320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11640c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(23 + mCodecSpecificDataSize < 128); 116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 116618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("esds"); 116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x03); // ES_DescrTag 117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(23 + mCodecSpecificDataSize); 117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x0000); // ES_ID 117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x1f); 117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x04); // DecoderConfigDescrTag 117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(15 + mCodecSpecificDataSize); 117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x11); // streamType VisualStream 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData[] = { 118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 0x77, 0x00, 118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00, 118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00 118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData, sizeof(kData)); 1187050b28a593350047845a45a14cc5026221ac1620James Dong 118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(mCodecSpecificDataSize); 119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData2[] = { 119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x06, // SLConfigDescriptorTag 119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x02 119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData2, sizeof(kData2)); 119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // esds 120118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("d263"); 120320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // vendor 120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // decoder version 120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(10); // level: 10 120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // profile: 0 120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // d263 121030ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 121130ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avcC"); 121230ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 121330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // avcC 121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 121530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 121630ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // mp4v, s263 or avc1 121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsd 121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stts"); 122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1222be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(mSttsTableEntries.size()); 1223be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1224be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSttsTableEntries.end(); ++it) { 1225be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleCount); 1226be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleDuration); 122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stts 122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1230050b28a593350047845a45a14cc5026221ac1620James Dong if (!is_audio) { 1231050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("stss"); 1232050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1233050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames 1234050b28a593350047845a45a14cc5026221ac1620James Dong for (List<int32_t>::iterator it = mStssTableEntries.begin(); 1235050b28a593350047845a45a14cc5026221ac1620James Dong it != mStssTableEntries.end(); ++it) { 1236050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(*it); 1237050b28a593350047845a45a14cc5026221ac1620James Dong } 1238050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // stss 1239050b28a593350047845a45a14cc5026221ac1620James Dong } 1240050b28a593350047845a45a14cc5026221ac1620James Dong 124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsz"); 124220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1243be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 1244be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SampleInfo>::iterator it = mSampleInfos.begin(); 1245be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->size); // default sample size 1246be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1247be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(0); 1248be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 124920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(mSampleInfos.size()); 1250be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (!mSamplesHaveSameSize) { 1251be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 1252be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSampleInfos.end(); ++it) { 1253be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32((*it).size); 1254be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsz 125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsc"); 125920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 126013aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(mStscTableEntries.size()); 126113aec890216948b0c364f8f92792129d0335f506James Dong for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 126213aec890216948b0c364f8f92792129d0335f506James Dong it != mStscTableEntries.end(); ++it) { 126313aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->firstChunk); 126413aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->samplesPerChunk); 126513aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->sampleDescriptionId); 126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 126720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsc 126820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 126920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("co64"); 127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 127113aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(mChunkOffsets.size()); 127213aec890216948b0c364f8f92792129d0335f506James Dong for (List<off_t>::iterator it = mChunkOffsets.begin(); 127313aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkOffsets.end(); ++it) { 127413aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt64((*it)); 127520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // co64 127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stbl 127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // mdia 128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // trak 128120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 128320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 1284