MPEG4Writer.cpp revision 050b28a593350047845a45a14cc5026221ac1620
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> 3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 3925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track(MPEG4Writer *owner, const sp<MediaSource> &source); 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t start(); 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void stop(); 4425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 463b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void writeTrackHeader(int32_t trackID); 4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 52693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 543b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t mMaxTimeStampUs; 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber struct SampleInfo { 5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t size; 6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset; 6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t timestamp; 6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber List<SampleInfo> mSampleInfos; 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 65050b28a593350047845a45a14cc5026221ac1620James Dong List<int32_t> mStssTableEntries; 66050b28a593350047845a45a14cc5026221ac1620James Dong 6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 69548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 7225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void threadEntry(); 7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t makeAVCCodecSpecificData( 7703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size); 7803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 8220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR 1 8403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 8520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFile(fopen(filename, "wb")), 8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mMdatOffset(0) { 890c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mFile != NULL); 9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9230ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 9330ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mFile(fdopen(fd, "wb")), 9430ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 9530ab66297501757d745b9ae10da61adcd891f497Andreas Huber mMdatOffset(0) { 9630ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(mFile != NULL); 9730ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 9830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 9920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1092dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 11025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track *track = new Track(this, source); 11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 1122dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 1132dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::start() { 11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 11825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("ftyp"); 12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); 12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mMdatOffset = mOffset; 12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber write("\x00\x00\x00\x01mdat????????", 16); 12920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 13225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t err = (*it)->start(); 13325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 13425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 13525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it2 = mTracks.begin(); 13625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it2 != it; ++it2) { 13725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber (*it2)->stop(); 13825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 13925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 14025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 14125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 14325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 14425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() { 14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t max_duration = 0; 15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->stop(); 15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1573b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t duration = (*it)->getDurationUs(); 15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (duration > max_duration) { 15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber max_duration = duration; 16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fseek(mFile, mMdatOffset + 8, SEEK_SET); 16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t size = mOffset - mMdatOffset; 16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size = hton64(size); 16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&size, 1, 8, mFile); 16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fseek(mFile, mOffset, SEEK_SET); 16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("moov"); 17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("mvhd"); 17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // version=0, flags=0 17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // creation time 17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // modification time 17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(1000); // timescale 1793b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber writeInt32(max_duration / 1000); 18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // rate 18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0x100); // volume 18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0); // reserved 18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // matrix 18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); 19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x40000000); 19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mTracks.size() + 1); // nextTrackID 20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // mvhd 20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t id = 1; 20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it, ++id) { 20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->writeTrackHeader(id); 20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // moov 20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2100c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fclose(mFile); 21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFile = NULL; 21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberoff_t MPEG4Writer::addSample(MediaBuffer *buffer) { 21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Mutex::Autolock autoLock(mLock); 21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t old_offset = mOffset; 22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1, buffer->range_length(), mFile); 22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 23003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 23103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 23203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 23303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 23503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 23603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 23703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 23803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 23903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 24003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 24103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 24203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 24330ab66297501757d745b9ae10da61adcd891f497Andreas Huberoff_t MPEG4Writer::addLengthPrefixedSample(MediaBuffer *buffer) { 24430ab66297501757d745b9ae10da61adcd891f497Andreas Huber Mutex::Autolock autoLock(mLock); 24530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 24603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber StripStartcode(buffer); 24703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 24830ab66297501757d745b9ae10da61adcd891f497Andreas Huber off_t old_offset = mOffset; 24930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 25030ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 25103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 25203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 25303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t x = length >> 24; 25403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 25503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 16) & 0xff; 25603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 25703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 8) & 0xff; 25803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 25903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = length & 0xff; 26003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 26103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 26230ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(length < 65536); 26330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 26430ab66297501757d745b9ae10da61adcd891f497Andreas Huber uint8_t x = length >> 8; 26530ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 26630ab66297501757d745b9ae10da61adcd891f497Andreas Huber x = length & 0xff; 26730ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 26803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 26930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 27030ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 27130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1, length, mFile); 27230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 27303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 27403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mOffset += length + 4; 27503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 27630ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset += length + 2; 27703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 27830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 27930ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 28030ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 28130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 2830c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.push_back(mOffset); 28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 2920c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset = *--mBoxes.end(); 29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fseek(mFile, offset, SEEK_SET); 29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mOffset - offset); 29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset -= 4; 30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fseek(mFile, mOffset, SEEK_SET); 30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&x, 1, 1, mFile); 30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++mOffset; 30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&x, 1, 2, mFile); 31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += 2; 31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&x, 1, 4, mFile); 31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += 4; 31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&x, 1, 8, mFile); 32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += 8; 32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(s, 1, n + 1, mFile); 33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += n + 1; 33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 3340c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(s, 1, 4, mFile); 33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += 4; 33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(data, 1, size, mFile); 34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += size; 34220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 34425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 34525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 34625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 34725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 34825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 34925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 35025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 35125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 35225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 35325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 35425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 35525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 35625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 36025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber MPEG4Writer *owner, const sp<MediaSource> &source) 36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 36225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 3653b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs(0), 36620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 36725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 368548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 36925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS(false) { 37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 38125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::Track::start() { 38225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t err = mSource->start(); 38325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 38425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 38525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 38625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 38725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 3943b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs = 0; 39525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 39725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 39925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 40025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() { 40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 40520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 40920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource->stop(); 41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 41625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 41725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 41825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 41925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track->threadEntry(); 42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 429548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h> 430548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) { 431548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber const uint8_t *data = (const uint8_t *)_data; 432548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t offset = 0; 433548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber while (offset < size) { 434548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("0x%04x ", offset); 435548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 436548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t n = size - offset; 437548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (n > 16) { 438548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber n = 16; 439548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 440548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 441548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < 16; ++i) { 442548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (i == 8) { 443548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 444548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 445548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 446548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (offset + i < size) { 447548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%02x ", data[offset + i]); 448548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 449548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 450548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 451548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 452548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 453548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 454548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 455548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < n; ++i) { 456548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (isprint(data[offset + i])) { 457548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%c", data[offset + i]); 458548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 459548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("."); 460548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 461548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 462548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 463548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("\n"); 464548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 465548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber offset += 16; 466548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 467548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber} 468548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 469548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 47003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 47103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 472548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber // hexdump(data, size); 473548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 47403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 475548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Already have codec specific data"); 47603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 47703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 47803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 47903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) { 480548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Must start with a start code"); 48103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 48203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 48303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 48403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamOffset = 4; 48503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber while (picParamOffset + 3 < size 48603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) { 48703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber ++picParamOffset; 48803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 48903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 49003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (picParamOffset + 3 >= size) { 491548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Could not find start-code for pictureParameterSet"); 49203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 49303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 49403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 49503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t seqParamSetLength = picParamOffset - 4; 49603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamSetLength = size - picParamOffset - 4; 49703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 49803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 49903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2; 50003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 50103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 50203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 50303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 50403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = 0x42; // profile 50503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = 0x80; 50603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[3] = 0x1e; // level 50703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 50803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 50903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 3; // length size == 4 bytes 51003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 51103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 1; // length size == 2 bytes 51203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 51303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 51403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[5] = 0xe0 | 1; 51503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[6] = seqParamSetLength >> 8; 51603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[7] = seqParamSetLength & 0xff; 51703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[8], &data[4], seqParamSetLength); 51803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header += 8 + seqParamSetLength; 51903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 52003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = picParamSetLength >> 8; 52103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = picParamSetLength & 0xff; 52203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength); 52303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 52403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 52503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 52603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() { 52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> meta = mSource->getFormat(); 52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber meta->findCString(kKeyMIMEType, &mime); 531050b28a593350047845a45a14cc5026221ac1620James Dong bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 532050b28a593350047845a45a14cc5026221ac1620James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 53330ab66297501757d745b9ae10da61adcd891f497Andreas Huber bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 53430ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (!mDone && mSource->read(&buffer) == OK) { 53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 54530ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 54630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 54703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 54803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 54903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 550548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 551548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 55203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (is_avc) { 55303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 55403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 55503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 55603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 55703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 55803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (err != OK) { 55903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber LOGE("failed to parse avc codec specific data."); 56030ab66297501757d745b9ae10da61adcd891f497Andreas Huber break; 56130ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 56203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } else if (is_mpeg4) { 56303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 56403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 56503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 56603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 56703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 56803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 56930ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 57030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 57130ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 57230ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 57330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 574548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 57530ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 576548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && 577548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber count == 1 && is_mpeg4 && mCodecSpecificData == NULL) { 57803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI mpeg4 encoder does not properly set the 57903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // codec-specific-data flag. 58030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *data = 58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const size_t size = buffer->range_length(); 58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t offset = 0; 58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (offset + 3 < size) { 58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (data[offset] == 0x00 && data[offset + 1] == 0x00 58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) { 59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++offset; 59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5960c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber // CHECK(offset + 3 < size); 597bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber if (offset + 3 >= size) { 598bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // XXX assume the entire first chunk of data is the codec specific 599bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // data. 600bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber offset = size; 601bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber } 60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificDataSize = offset; 60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = malloc(offset); 60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber memcpy(mCodecSpecificData, data, offset); 60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->set_range(buffer->range_offset() + offset, size - offset); 60803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 60903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size == offset) { 61003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 61103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 61203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 61303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 61403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 615548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 616548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 617548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && is_avc && count < 3) { 61803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI video encoder does not flag codec specific data 61903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // as such and also splits up SPS and PPS across two buffers. 62003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 62103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data = 62203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 62303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 62403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t size = buffer->range_length(); 62503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 62603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber CHECK(count == 2 || mCodecSpecificData == NULL); 62703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 62803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t offset = mCodecSpecificDataSize; 62903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize += size + 4; 63003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = 63103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber realloc(mCodecSpecificData, mCodecSpecificDataSize); 63203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 63303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset, 63403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber "\x00\x00\x00\x01", 4); 63503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 63603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size); 63703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 63803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 63903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 64003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 64103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (count == 2) { 64203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber void *tmp = mCodecSpecificData; 64303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size = mCodecSpecificDataSize; 64403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = NULL; 64503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 0; 64603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 64703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 64803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)tmp, size); 64903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 65003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber free(tmp); 65103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber tmp = NULL; 65203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 65303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (err != OK) { 65403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber LOGE("failed to parse avc codec specific data."); 65503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber break; 65603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 657548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 658548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 65903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 66003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 66103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 66430ab66297501757d745b9ae10da61adcd891f497Andreas Huber off_t offset = is_avc ? mOwner->addLengthPrefixedSample(buffer) 66530ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mOwner->addSample(buffer); 66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber SampleInfo info; 66803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber info.size = is_avc 66903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 67003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber ? buffer->range_length() + 4 67103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 67203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber ? buffer->range_length() + 2 67303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 67403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber : buffer->range_length(); 67503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber info.offset = offset; 67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 678050b28a593350047845a45a14cc5026221ac1620James Dong 679050b28a593350047845a45a14cc5026221ac1620James Dong bool is_audio = !strncasecmp(mime, "audio/", 6); 680050b28a593350047845a45a14cc5026221ac1620James Dong 68148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int64_t timestampUs; 68248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); 68348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 6843b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber if (timestampUs > mMaxTimeStampUs) { 6853b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs = timestampUs; 6863b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 6873b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 68848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber // Our timestamp is in ms. 68948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber info.timestamp = (timestampUs + 500) / 1000; 69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSampleInfos.push_back(info); 69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 693050b28a593350047845a45a14cc5026221ac1620James Dong int32_t isSync = false; 694050b28a593350047845a45a14cc5026221ac1620James Dong buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync); 695050b28a593350047845a45a14cc5026221ac1620James Dong if (isSync) { 696050b28a593350047845a45a14cc5026221ac1620James Dong mStssTableEntries.push_back(mSampleInfos.size()); 697050b28a593350047845a45a14cc5026221ac1620James Dong } 698050b28a593350047845a45a14cc5026221ac1620James Dong // Our timestamp is in ms. 69920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 70225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 70325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7063b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 7073b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber return mMaxTimeStampUs; 70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { 71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findCString(kKeyMIMEType, &mime); 7130c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool is_audio = !strncasecmp(mime, "audio/", 6); 71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 71820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("trak"); 72020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 72120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("tkhd"); 72220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 72320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(trackID); 72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 7273b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mOwner->writeInt32(getDurationUs() / 1000); 72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // layer 73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // alternate group 73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(is_audio ? 0x100 : 0); // volume 73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); // matrix 73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); 74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x40000000); 74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 7520c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 754050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 755050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // tkhd 75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdia"); 76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdhd"); 76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1000); // timescale 7663b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mOwner->writeInt32(getDurationUs() / 1000); 76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // language code XXX 76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("hdlr"); 77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 773050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // component type: should be mhlr 774050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeFourcc(is_audio ? "soun" : "vide"); // component subtype 77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 778050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeCString("SoundHandler"); // name 77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("minf"); 78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("smhd"); 78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // balance 78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 78720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 78920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("vmhd"); 79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x00000001); // version=0, flags=1 79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // graphics mode 79220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // opcolor 79320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 79620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 797050b28a593350047845a45a14cc5026221ac1620James Dong 798050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dinf"); 799050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dref"); 800050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 801050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(1); 802050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("url "); 803050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(1); // version=0, flags=1 804050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // url 805050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dref 806050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dinf 807050b28a593350047845a45a14cc5026221ac1620James Dong 808050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // minf 80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stbl"); 81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsd"); 81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); // entry count 81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 81625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber const char *fourcc = NULL; 81718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 81825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "samr"; 81918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 82025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "sawb"; 821050b28a593350047845a45a14cc5026221ac1620James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 822050b28a593350047845a45a14cc5026221ac1620James Dong fourcc = "mp4a"; 82325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } else { 82425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 82525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber CHECK(!"should not be here, unknown mime type."); 82625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 82725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 82825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mOwner->beginBox(fourcc); // audio format 82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 831050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x1); // data ref index 83220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 83320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 834050b28a593350047845a45a14cc5026221ac1620James Dong int32_t nChannels; 835050b28a593350047845a45a14cc5026221ac1620James Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 836050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(nChannels); // channel count 83720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(16); // sample size 83820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 84020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t samplerate; 84220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 8430c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 84520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(samplerate << 16); 846050b28a593350047845a45a14cc5026221ac1620James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 847050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("esds"); 848050b28a593350047845a45a14cc5026221ac1620James Dong 849050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 850050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x03); // ES_DescrTag 851050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 852050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x0000);// ES_ID 853050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); 854050b28a593350047845a45a14cc5026221ac1620James Dong 855050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 856050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 857050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 858050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x15); // streamType AudioStream 859050b28a593350047845a45a14cc5026221ac1620James Dong 860050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x03); // XXX 861050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); // buffer size 24-bit 862050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // max bit rate 863050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // avg bit rate 864050b28a593350047845a45a14cc5026221ac1620James Dong 865050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 866050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(mCodecSpecificDataSize); 867050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 868050b28a593350047845a45a14cc5026221ac1620James Dong 869050b28a593350047845a45a14cc5026221ac1620James Dong static const uint8_t kData2[] = { 870050b28a593350047845a45a14cc5026221ac1620James Dong 0x06, // SLConfigDescriptorTag 871050b28a593350047845a45a14cc5026221ac1620James Dong 0x01, 872050b28a593350047845a45a14cc5026221ac1620James Dong 0x02 873050b28a593350047845a45a14cc5026221ac1620James Dong }; 874050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(kData2, sizeof(kData2)); 875050b28a593350047845a45a14cc5026221ac1620James Dong 876050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // esds 877050b28a593350047845a45a14cc5026221ac1620James Dong } 87820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 87920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 88018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 88120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mp4v"); 88218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 88320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("s263"); 88430ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 88530ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avc1"); 88620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 88725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 8880c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!"should not be here, unknown mime type."); 88920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 89020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 89120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 89220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 89320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // data ref index 89420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 89520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 89620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 89720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 89820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 90020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 90120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 90220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 9030c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(width); 90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(height); 90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // horiz resolution 90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // vert resolution 90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(1); // frame count 91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(" ", 32); 91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x18); // depth 91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(-1); // predefined 91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9150c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(23 + mCodecSpecificDataSize < 128); 91620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 91718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("esds"); 91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 92120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x03); // ES_DescrTag 92320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(23 + mCodecSpecificDataSize); 92420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x0000); // ES_ID 92520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x1f); 92620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x04); // DecoderConfigDescrTag 92820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(15 + mCodecSpecificDataSize); 92920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x11); // streamType VisualStream 93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData[] = { 93320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 0x77, 0x00, 93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00, 93520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00 93620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 93720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData, sizeof(kData)); 938050b28a593350047845a45a14cc5026221ac1620James Dong 93920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 94120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(mCodecSpecificDataSize); 94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 94420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData2[] = { 94520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x06, // SLConfigDescriptorTag 94620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 94720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x02 94820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData2, sizeof(kData2)); 95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // esds 95218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("d263"); 95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // vendor 95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // decoder version 95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(10); // level: 10 95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // profile: 0 95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // d263 96130ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 96230ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avcC"); 96330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 96430ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // avcC 96520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 96630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 96730ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // mp4v, s263 or avc1 96820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsd 97020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 97120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stts"); 97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 97303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mOwner->writeInt32(mSampleInfos.size()); 97420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber List<SampleInfo>::iterator it = mSampleInfos.begin(); 97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t last = (*it).timestamp; 97703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int64_t lastDuration = 1; 97803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++it; 98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (it != mSampleInfos.end()) { 98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); 98203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber lastDuration = (*it).timestamp - last; 98303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mOwner->writeInt32(lastDuration); 98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber last = (*it).timestamp; 98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++it; 98820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 98903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 99003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // We don't really know how long the last frame lasts, since 99103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // there is no frame time after it, just repeat the previous 99203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // frame's duration. 99303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mOwner->writeInt32(1); 99403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mOwner->writeInt32(lastDuration); 99503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 99620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stts 99720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 998050b28a593350047845a45a14cc5026221ac1620James Dong if (!is_audio) { 999050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("stss"); 1000050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1001050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames 1002050b28a593350047845a45a14cc5026221ac1620James Dong for (List<int32_t>::iterator it = mStssTableEntries.begin(); 1003050b28a593350047845a45a14cc5026221ac1620James Dong it != mStssTableEntries.end(); ++it) { 1004050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(*it); 1005050b28a593350047845a45a14cc5026221ac1620James Dong } 1006050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // stss 1007050b28a593350047845a45a14cc5026221ac1620James Dong } 1008050b28a593350047845a45a14cc5026221ac1620James Dong 100920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsz"); 101020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 101120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // default sample size 101220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(mSampleInfos.size()); 101320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 101420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mSampleInfos.end(); ++it) { 101520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32((*it).size); 101620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 101720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsz 101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 101920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsc"); 102020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 102120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(mSampleInfos.size()); 102220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t n = 1; 102320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mSampleInfos.end(); ++it, ++n) { 102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(n); 102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); 102720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); 102820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 102920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsc 103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("co64"); 103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 103320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(mSampleInfos.size()); 103420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 1035050b28a593350047845a45a14cc5026221ac1620James Dong it != mSampleInfos.end(); ++it) { 103620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt64((*it).offset); 103720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 103820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // co64 103920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 104020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stbl 104120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // mdia 104220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // trak 104320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 104420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 1046