MPEG4Writer.cpp revision e136c3bb38e88315bf8797a464ebf2c788296b22
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; 1013c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 10225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void threadEntry(); 10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t makeAVCCodecSpecificData( 10703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size); 10813aec890216948b0c364f8f92792129d0335f506James Dong void writeOneChunk(bool isAvc); 10903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR 1 11503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 11620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFile(fopen(filename, "wb")), 11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 11913aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1207837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 12113aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs(500000) { 1220c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mFile != NULL); 12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12530ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 12630ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mFile(fdopen(fd, "wb")), 12730ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 12813aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1297837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 13013aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs(500000) { 13130ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(mFile != NULL); 13230ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 13330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 13420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1442dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 14525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track *track = new Track(this, source); 14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 1472dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 1482dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::start() { 15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 15325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1563c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mStartTimestampUs = 0; 1577837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = true; 1587837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 1597837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 1607837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 1617837c17063a4c50bc856ba59418516fdab731de7James Dong 16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("ftyp"); 16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); 16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1687837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1707837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 1717837c17063a4c50bc856ba59418516fdab731de7James Dong // XXX: Estimate the moov box size 1727837c17063a4c50bc856ba59418516fdab731de7James Dong // based on max file size or duration limit 1737837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize = 0x0F00; 1747837c17063a4c50bc856ba59418516fdab731de7James Dong } 1757837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mEstimatedMoovBoxSize >= 8); 1767837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 1777837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize); 1787837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 1797837c17063a4c50bc856ba59418516fdab731de7James Dong 1807837c17063a4c50bc856ba59418516fdab731de7James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 1817837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 1827837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 1837837c17063a4c50bc856ba59418516fdab731de7James Dong write("\x00\x00\x00\x01mdat????????", 16); 18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 18625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t err = (*it)->start(); 18725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 18825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 18925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it2 = mTracks.begin(); 19025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it2 != it; ++it2) { 19125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber (*it2)->stop(); 19225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 19325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 19425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 19525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 19725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 19825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() { 20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t max_duration = 0; 20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->stop(); 21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2113b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t duration = (*it)->getDurationUs(); 21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (duration > max_duration) { 21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber max_duration = duration; 21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2177837c17063a4c50bc856ba59418516fdab731de7James Dong 21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 2197837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mMdatOffset + 8, SEEK_SET); 22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t size = mOffset - mMdatOffset; 22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size = hton64(size); 22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&size, 1, 8, mFile); 2237837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 2267837c17063a4c50bc856ba59418516fdab731de7James Dong const off_t moovOffset = mOffset; 2277837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = true; 2287837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 2297837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 2307837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("moov"); 23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("mvhd"); 23520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // version=0, flags=0 23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // creation time 23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // modification time 23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(1000); // timescale 2393b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber writeInt32(max_duration / 1000); 24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // rate 24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0x100); // volume 24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0); // reserved 24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // matrix 24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); 25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x40000000); 25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mTracks.size() + 1); // nextTrackID 26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // mvhd 26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t id = 1; 26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it, ++id) { 26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->writeTrackHeader(id); 26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // moov 26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2707837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 2717837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 2727837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 2737837c17063a4c50bc856ba59418516fdab731de7James Dong 2747837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 2757837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 2767837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 2777837c17063a4c50bc856ba59418516fdab731de7James Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); 2787837c17063a4c50bc856ba59418516fdab731de7James Dong 2797837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 2807837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mStreamableFile? mOffset: mFreeBoxOffset; 2817837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 2827837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 2837837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 2847837c17063a4c50bc856ba59418516fdab731de7James Dong 2857837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 2867837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 2877837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 2887837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 2897837c17063a4c50bc856ba59418516fdab731de7James Dong } 2907837c17063a4c50bc856ba59418516fdab731de7James Dong 2910c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2937837c17063a4c50bc856ba59418516fdab731de7James Dong fflush(mFile); 29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fclose(mFile); 29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFile = NULL; 29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29813aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 29913aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 30013aec890216948b0c364f8f92792129d0335f506James Dong return OK; 30113aec890216948b0c364f8f92792129d0335f506James Dong} 30213aec890216948b0c364f8f92792129d0335f506James Dong 30313aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 30413aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 30513aec890216948b0c364f8f92792129d0335f506James Dong} 30613aec890216948b0c364f8f92792129d0335f506James Dong 30713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 30813aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 30913aec890216948b0c364f8f92792129d0335f506James Dong} 31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31113aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t old_offset = mOffset; 31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1, buffer->range_length(), mFile); 31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 32303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 32403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 32503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 32603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 32703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 32803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 32903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 33003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 33103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 33203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 33303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 33403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 33503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 33613aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 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 467956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(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 5033c0131f02b6f008321608044c53bccce2ac5f6ddJames Dongvoid MPEG4Writer::setStartTimestamp(int64_t timeUs) { 5043c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong LOGI("setStartTimestamp: %lld", timeUs); 5053c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 5063c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong if (mStartTimestampUs != 0) { 5073c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return; // Sorry, too late 5083c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 5093c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mStartTimestampUs = timeUs; 5103c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 5113c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 5123c0131f02b6f008321608044c53bccce2ac5f6ddJames Dongint64_t MPEG4Writer::getStartTimestamp() { 5133c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong LOGI("getStartTimestamp: %lld", mStartTimestampUs); 5143c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 5153c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 5163c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 5173c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 52020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 52125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber MPEG4Writer *owner, const sp<MediaSource> &source) 52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 52325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 5263b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs(0), 527956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 528be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 53025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 531548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 53225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS(false) { 53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 53520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 54425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::Track::start() { 54525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t err = mSource->start(); 54625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 54725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 54825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 54925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 55025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 5573b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs = 0; 55825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 559956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 56325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 56425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() { 56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource->stop(); 57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 58125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 58225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 58325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track->threadEntry(); 58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 593548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h> 594548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) { 595548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber const uint8_t *data = (const uint8_t *)_data; 596548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t offset = 0; 597548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber while (offset < size) { 598548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("0x%04x ", offset); 599548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 600548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t n = size - offset; 601548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (n > 16) { 602548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber n = 16; 603548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 604548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 605548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < 16; ++i) { 606548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (i == 8) { 607548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 608548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 609548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 610548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (offset + i < size) { 611548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%02x ", data[offset + i]); 612548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 613548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 614548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 615548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 616548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 617548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 618548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 619548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < n; ++i) { 620548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (isprint(data[offset + i])) { 621548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%c", data[offset + i]); 622548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 623548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("."); 624548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 625548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 626548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 627548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("\n"); 628548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 629548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber offset += 16; 630548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 631548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber} 632548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 633548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 63403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 63503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 636548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber // hexdump(data, size); 637548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 63803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 639548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Already have codec specific data"); 64003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 64103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 64203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 64303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) { 644548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Must start with a start code"); 64503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 64603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 64703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 64803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamOffset = 4; 64903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber while (picParamOffset + 3 < size 65003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) { 65103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber ++picParamOffset; 65203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 65303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 65403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (picParamOffset + 3 >= size) { 655548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Could not find start-code for pictureParameterSet"); 65603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 65703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 65803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 65903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t seqParamSetLength = picParamOffset - 4; 66003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamSetLength = size - picParamOffset - 4; 66103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 66203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 66303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2; 66403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 66503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 66603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 66703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 66803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = 0x42; // profile 66903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = 0x80; 67003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[3] = 0x1e; // level 67103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 67203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 67303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 3; // length size == 4 bytes 67403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 67503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 1; // length size == 2 bytes 67603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 67703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 67803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[5] = 0xe0 | 1; 67903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[6] = seqParamSetLength >> 8; 68003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[7] = seqParamSetLength & 0xff; 68103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[8], &data[4], seqParamSetLength); 68203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header += 8 + seqParamSetLength; 68303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 68403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = picParamSetLength >> 8; 68503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = picParamSetLength & 0xff; 68603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength); 68703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 68803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 68903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 69003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() { 69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> meta = mSource->getFormat(); 69320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber meta->findCString(kKeyMIMEType, &mime); 695050b28a593350047845a45a14cc5026221ac1620James Dong bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 696050b28a593350047845a45a14cc5026221ac1620James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 69730ab66297501757d745b9ae10da61adcd891f497Andreas Huber bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 698956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bool is_audio = !strncasecmp(mime, "audio/", 6); 69930ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 70013aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 70113aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 70213aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 70313aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 704be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong int64_t lastTimestamp = 0; // Timestamp of the previous sample 705be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong int64_t lastDuration = 0; // Time spacing between the previous two samples 706be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 707be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (!mDone && mSource->read(&buffer) == OK) { 71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 71320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 71413aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 71830ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 71930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 72003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 72103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 72203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 723548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 724548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 72503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (is_avc) { 72603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 72703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 72803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 72903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 730be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 73103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } else if (is_mpeg4) { 73203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 73303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 73403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 73503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 73603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 73703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 73830ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 73930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 74030ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 74130ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 74230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 743548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 74430ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 745548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && 746548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber count == 1 && is_mpeg4 && mCodecSpecificData == NULL) { 74703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI mpeg4 encoder does not properly set the 74803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // codec-specific-data flag. 74930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *data = 75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const size_t size = buffer->range_length(); 75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t offset = 0; 75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (offset + 3 < size) { 75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (data[offset] == 0x00 && data[offset + 1] == 0x00 75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) { 75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++offset; 76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7650c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber // CHECK(offset + 3 < size); 766bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber if (offset + 3 >= size) { 767bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // XXX assume the entire first chunk of data is the codec specific 768bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // data. 769bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber offset = size; 770bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber } 77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificDataSize = offset; 77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = malloc(offset); 77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber memcpy(mCodecSpecificData, data, offset); 77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->set_range(buffer->range_offset() + offset, size - offset); 77703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 77803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size == offset) { 77903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 78003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 78103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 78203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 78303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 784548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 785548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 786548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && is_avc && count < 3) { 78703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI video encoder does not flag codec specific data 78803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // as such and also splits up SPS and PPS across two buffers. 78903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 79003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data = 79103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 79203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 79303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t size = buffer->range_length(); 79403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 79503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber CHECK(count == 2 || mCodecSpecificData == NULL); 79603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 79703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t offset = mCodecSpecificDataSize; 79803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize += size + 4; 79903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = 80003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber realloc(mCodecSpecificData, mCodecSpecificDataSize); 80103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 80203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset, 80303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber "\x00\x00\x00\x01", 4); 80403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 80503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size); 80603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 80703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 80803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 80903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 81003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (count == 2) { 81103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber void *tmp = mCodecSpecificData; 81203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size = mCodecSpecificDataSize; 81303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = NULL; 81403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 0; 81503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 81603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 81703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)tmp, size); 81803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber free(tmp); 81903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber tmp = NULL; 820be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 821548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 822548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 82303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 82403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 82503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 828e136c3bb38e88315bf8797a464ebf2c788296b22James Dong if (is_avc) StripStartcode(buffer); 829e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber SampleInfo info; 83103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber info.size = is_avc 83203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 83313aec890216948b0c364f8f92792129d0335f506James Dong ? buffer->range_length() + 4 83403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 83513aec890216948b0c364f8f92792129d0335f506James Dong ? buffer->range_length() + 2 83603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 83713aec890216948b0c364f8f92792129d0335f506James Dong : buffer->range_length(); 838050b28a593350047845a45a14cc5026221ac1620James Dong 839d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 840d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mEstimatedTrackSizeBytes += info.size; 841d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 842d599cd4573b5a2d5914c5040e0565ef866749b77James Dong buffer->release(); 843d599cd4573b5a2d5914c5040e0565ef866749b77James Dong buffer = NULL; 844d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 845d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 846d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 847d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 848d599cd4573b5a2d5914c5040e0565ef866749b77James Dong buffer->release(); 849d599cd4573b5a2d5914c5040e0565ef866749b77James Dong buffer = NULL; 850d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 851d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 852d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 853d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 854050b28a593350047845a45a14cc5026221ac1620James Dong 85548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int64_t timestampUs; 85648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); 8573c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong if (mSampleInfos.empty()) { 8583c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->setStartTimestamp(timestampUs); 8593c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mStartTimestampUs = (timestampUs - mOwner->getStartTimestamp()); 8603c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 86148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 8623b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber if (timestampUs > mMaxTimeStampUs) { 8633b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs = timestampUs; 8643b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 8653b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 86648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber // Our timestamp is in ms. 86748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber info.timestamp = (timestampUs + 500) / 1000; 86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSampleInfos.push_back(info); 869be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() > 2) { 870be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (lastDuration != info.timestamp - lastTimestamp) { 871be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong SttsTableEntry sttsEntry(sampleCount, lastDuration); 872be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSttsTableEntries.push_back(sttsEntry); 873be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 874be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 875be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 876be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 877be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 878be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 879be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() >= 2 && previousSampleSize != info.size) { 880be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 881be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 882be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong previousSampleSize = info.size; 883be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 884be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong lastDuration = info.timestamp - lastTimestamp; 885be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong lastTimestamp = info.timestamp; 88620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 88713aec890216948b0c364f8f92792129d0335f506James Dong//////////////////////////////////////////////////////////////////////////////// 88813aec890216948b0c364f8f92792129d0335f506James Dong // Make a deep copy of the MediaBuffer less Metadata 88913aec890216948b0c364f8f92792129d0335f506James Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 89013aec890216948b0c364f8f92792129d0335f506James Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 89113aec890216948b0c364f8f92792129d0335f506James Dong buffer->range_length()); 89213aec890216948b0c364f8f92792129d0335f506James Dong copy->set_range(0, buffer->range_length()); 89313aec890216948b0c364f8f92792129d0335f506James Dong 89413aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 89513aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 89613aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(++nChunks, 1, 1); 89713aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 89813aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 89913aec890216948b0c364f8f92792129d0335f506James Dong } else { 90013aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 90113aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 90213aec890216948b0c364f8f92792129d0335f506James Dong } else { 90313aec890216948b0c364f8f92792129d0335f506James Dong if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 90413aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 90513aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 90613aec890216948b0c364f8f92792129d0335f506James Dong (--(mStscTableEntries.end()))->samplesPerChunk != 90713aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size()) { 90813aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(nChunks, 90913aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size(), 1); 91013aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 91113aec890216948b0c364f8f92792129d0335f506James Dong } 91213aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 91313aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 91413aec890216948b0c364f8f92792129d0335f506James Dong } 91513aec890216948b0c364f8f92792129d0335f506James Dong } 91613aec890216948b0c364f8f92792129d0335f506James Dong } 91713aec890216948b0c364f8f92792129d0335f506James Dong 918050b28a593350047845a45a14cc5026221ac1620James Dong int32_t isSync = false; 91913aec890216948b0c364f8f92792129d0335f506James Dong if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync) && 92013aec890216948b0c364f8f92792129d0335f506James Dong isSync != 0) { 921050b28a593350047845a45a14cc5026221ac1620James Dong mStssTableEntries.push_back(mSampleInfos.size()); 922050b28a593350047845a45a14cc5026221ac1620James Dong } 923be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 92420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 92520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 92620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 92725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 928f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong if (mSampleInfos.empty()) { 929f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_STOP_PREMATURELY, 0); 930f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 931be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 93213aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 93313aec890216948b0c364f8f92792129d0335f506James Dong if (!mChunkSamples.empty()) { 93413aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 93513aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1); 93613aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 93713aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 93813aec890216948b0c364f8f92792129d0335f506James Dong } 93913aec890216948b0c364f8f92792129d0335f506James Dong 940be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 941be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 942be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 943be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() == 1) { 944be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong lastDuration = 0; // A single sample's duration 945be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 946be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 947be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 948be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong SttsTableEntry sttsEntry(sampleCount, lastDuration); 949be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSttsTableEntries.push_back(sttsEntry); 95025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 951956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s", 952956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong count, nZeroLengthFrames, mSampleInfos.size(), is_audio? "audio": "video"); 95313aec890216948b0c364f8f92792129d0335f506James Dong} 95413aec890216948b0c364f8f92792129d0335f506James Dong 95513aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::Track::writeOneChunk(bool isAvc) { 95613aec890216948b0c364f8f92792129d0335f506James Dong mOwner->lock(); 95713aec890216948b0c364f8f92792129d0335f506James Dong for (List<MediaBuffer *>::iterator it = mChunkSamples.begin(); 95813aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkSamples.end(); ++it) { 95913aec890216948b0c364f8f92792129d0335f506James Dong off_t offset = isAvc? mOwner->addLengthPrefixedSample_l(*it) 96013aec890216948b0c364f8f92792129d0335f506James Dong : mOwner->addSample_l(*it); 96113aec890216948b0c364f8f92792129d0335f506James Dong if (it == mChunkSamples.begin()) { 96213aec890216948b0c364f8f92792129d0335f506James Dong mChunkOffsets.push_back(offset); 96313aec890216948b0c364f8f92792129d0335f506James Dong } 96413aec890216948b0c364f8f92792129d0335f506James Dong } 96513aec890216948b0c364f8f92792129d0335f506James Dong mOwner->unlock(); 96613aec890216948b0c364f8f92792129d0335f506James Dong while (!mChunkSamples.empty()) { 96713aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *>::iterator it = mChunkSamples.begin(); 96813aec890216948b0c364f8f92792129d0335f506James Dong (*it)->release(); 96913aec890216948b0c364f8f92792129d0335f506James Dong (*it) = NULL; 97013aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.erase(it); 97113aec890216948b0c364f8f92792129d0335f506James Dong } 97213aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 97320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 97420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9753b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 9763b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber return mMaxTimeStampUs; 97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 979d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 980d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 981d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 982d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { 98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findCString(kKeyMIMEType, &mime); 9860c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 98820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool is_audio = !strncasecmp(mime, "audio/", 6); 98920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 99020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 99120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 99220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("trak"); 99320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 99420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("tkhd"); 99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 99620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 99720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 99820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(trackID); 99920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 10003b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mOwner->writeInt32(getDurationUs() / 1000); 100120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 100220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 100320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // layer 100420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // alternate group 100520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(is_audio ? 0x100 : 0); // volume 100620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 100720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 100820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); // matrix 100920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 101020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 101120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 101220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); 101320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 101420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 101520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 101620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x40000000); 101720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 101920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 102020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 10250c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1027050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 1028050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 102920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // tkhd 103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10323c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong if (mStartTimestampUs != 0) { 10333c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("edts"); 10343c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->writeInt32(0); // version=0, flags=0 10353c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("elst"); 10363c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->writeInt32(0); // version=0, flags=0 10373c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->writeInt32(1); // a single entry 10383c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->writeInt32(mStartTimestampUs / 1000); // edit duration 1039956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mOwner->writeInt32(-1); // empty edit box to signal starting time offset 10403c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->writeInt32(1); // x1 rate 10413c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 10423c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 10433c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 10443c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdia"); 104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 104720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdhd"); 104820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 104920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 105020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 105120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1000); // timescale 10523b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mOwner->writeInt32(getDurationUs() / 1000); 105320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // language code XXX 105420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 105720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("hdlr"); 105820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1059050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // component type: should be mhlr 1060050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeFourcc(is_audio ? "soun" : "vide"); // component subtype 106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 106320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 1064956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mOwner->writeCString(is_audio ? "SoundHandler": ""); // name 106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 106620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 106720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("minf"); 106820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 106920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("smhd"); 107020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 107120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // balance 107220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 107320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 107420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 107520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("vmhd"); 107620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x00000001); // version=0, flags=1 107720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // graphics mode 107820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // opcolor 107920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 108020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 108120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 108220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1083050b28a593350047845a45a14cc5026221ac1620James Dong 1084050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dinf"); 1085050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dref"); 1086050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1087050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(1); 1088050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("url "); 1089050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(1); // version=0, flags=1 1090050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // url 1091050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dref 1092050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dinf 1093050b28a593350047845a45a14cc5026221ac1620James Dong 1094050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // minf 109520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 109620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stbl"); 109720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsd"); 109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 110020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); // entry count 110120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 110225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber const char *fourcc = NULL; 110318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 110425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "samr"; 110518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 110625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "sawb"; 1107050b28a593350047845a45a14cc5026221ac1620James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1108050b28a593350047845a45a14cc5026221ac1620James Dong fourcc = "mp4a"; 110925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } else { 111025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 111125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber CHECK(!"should not be here, unknown mime type."); 111225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 111325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 111425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mOwner->beginBox(fourcc); // audio format 111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 111620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 1117050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x1); // data ref index 111820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 1120050b28a593350047845a45a14cc5026221ac1620James Dong int32_t nChannels; 1121050b28a593350047845a45a14cc5026221ac1620James Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 1122050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(nChannels); // channel count 112320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(16); // sample size 112420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 112520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 112620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 112720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t samplerate; 112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 11290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 113020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 113120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(samplerate << 16); 1132050b28a593350047845a45a14cc5026221ac1620James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1133050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("esds"); 1134050b28a593350047845a45a14cc5026221ac1620James Dong 1135050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1136050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x03); // ES_DescrTag 1137050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 1138050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x0000);// ES_ID 1139050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); 1140050b28a593350047845a45a14cc5026221ac1620James Dong 1141050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 1142050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 1143050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 1144050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x15); // streamType AudioStream 1145050b28a593350047845a45a14cc5026221ac1620James Dong 1146050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x03); // XXX 1147050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); // buffer size 24-bit 1148050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // max bit rate 1149050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // avg bit rate 1150050b28a593350047845a45a14cc5026221ac1620James Dong 1151050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 1152050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(mCodecSpecificDataSize); 1153050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 1154050b28a593350047845a45a14cc5026221ac1620James Dong 1155050b28a593350047845a45a14cc5026221ac1620James Dong static const uint8_t kData2[] = { 1156050b28a593350047845a45a14cc5026221ac1620James Dong 0x06, // SLConfigDescriptorTag 1157050b28a593350047845a45a14cc5026221ac1620James Dong 0x01, 1158050b28a593350047845a45a14cc5026221ac1620James Dong 0x02 1159050b28a593350047845a45a14cc5026221ac1620James Dong }; 1160050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(kData2, sizeof(kData2)); 1161050b28a593350047845a45a14cc5026221ac1620James Dong 1162050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // esds 1163050b28a593350047845a45a14cc5026221ac1620James Dong } 116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 116618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mp4v"); 116818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("s263"); 117030ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 117130ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avc1"); 117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 117325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 11740c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!"should not be here, unknown mime type."); 117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // data ref index 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 11890c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(width); 119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(height); 119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // horiz resolution 119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // vert resolution 119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(1); // frame count 119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(" ", 32); 119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x18); // depth 119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(-1); // predefined 120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12010c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(23 + mCodecSpecificDataSize < 128); 120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("esds"); 120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x03); // ES_DescrTag 120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(23 + mCodecSpecificDataSize); 121020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x0000); // ES_ID 121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x1f); 121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x04); // DecoderConfigDescrTag 121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(15 + mCodecSpecificDataSize); 121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x11); // streamType VisualStream 121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData[] = { 121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 0x77, 0x00, 122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00, 122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00 122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 122320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData, sizeof(kData)); 1224050b28a593350047845a45a14cc5026221ac1620James Dong 122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(mCodecSpecificDataSize); 122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData2[] = { 123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x06, // SLConfigDescriptorTag 123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x02 123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData2, sizeof(kData2)); 123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // esds 123818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("d263"); 124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // vendor 124220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // decoder version 124320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(10); // level: 10 124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // profile: 0 124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // d263 124730ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 124830ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avcC"); 124930ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 125030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // avcC 125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 125230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 125330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // mp4v, s263 or avc1 125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsd 125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stts"); 125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1259be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(mSttsTableEntries.size()); 1260be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1261be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSttsTableEntries.end(); ++it) { 1262be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleCount); 1263be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleDuration); 126420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stts 126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1267050b28a593350047845a45a14cc5026221ac1620James Dong if (!is_audio) { 1268050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("stss"); 1269050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1270050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames 1271050b28a593350047845a45a14cc5026221ac1620James Dong for (List<int32_t>::iterator it = mStssTableEntries.begin(); 1272050b28a593350047845a45a14cc5026221ac1620James Dong it != mStssTableEntries.end(); ++it) { 1273050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(*it); 1274050b28a593350047845a45a14cc5026221ac1620James Dong } 1275050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // stss 1276050b28a593350047845a45a14cc5026221ac1620James Dong } 1277050b28a593350047845a45a14cc5026221ac1620James Dong 127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsz"); 127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1280be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 1281be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SampleInfo>::iterator it = mSampleInfos.begin(); 1282be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->size); // default sample size 1283be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1284be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(0); 1285be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(mSampleInfos.size()); 1287be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (!mSamplesHaveSameSize) { 1288be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 1289be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSampleInfos.end(); ++it) { 1290be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32((*it).size); 1291be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsz 129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsc"); 129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 129713aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(mStscTableEntries.size()); 129813aec890216948b0c364f8f92792129d0335f506James Dong for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 129913aec890216948b0c364f8f92792129d0335f506James Dong it != mStscTableEntries.end(); ++it) { 130013aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->firstChunk); 130113aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->samplesPerChunk); 130213aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->sampleDescriptionId); 130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsc 130520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 130620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("co64"); 130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 130813aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(mChunkOffsets.size()); 130913aec890216948b0c364f8f92792129d0335f506James Dong for (List<off_t>::iterator it = mChunkOffsets.begin(); 131013aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkOffsets.end(); ++it) { 131113aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt64((*it)); 131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // co64 131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 131520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stbl 131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // mdia 131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // trak 131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 1321