MPEG4Writer.cpp revision 2dce41ad26cb3e9e15c9e456a84bcf5309548ca0
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 1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h> 1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h> 2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h> 2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 250c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h> 2618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 3120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 3425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track(MPEG4Writer *owner, const sp<MediaSource> &source); 3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t start(); 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void stop(); 3925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t getDuration() const; 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void writeTrackHeader(int32_t trackID); 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 47693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber struct SampleInfo { 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t size; 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset; 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t timestamp; 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber List<SampleInfo> mSampleInfos; 5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 6325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void threadEntry(); 6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFile(fopen(filename, "wb")), 7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mMdatOffset(0) { 750c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mFile != NULL); 7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7830ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 7930ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mFile(fdopen(fd, "wb")), 8030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 8130ab66297501757d745b9ae10da61adcd891f497Andreas Huber mMdatOffset(0) { 8230ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(mFile != NULL); 8330ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 8430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 8520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 952dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 9625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track *track = new Track(this, source); 9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 982dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 992dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::start() { 10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 10425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("ftyp"); 10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); 11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mMdatOffset = mOffset; 11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber write("\x00\x00\x00\x01mdat????????", 16); 11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 11825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t err = (*it)->start(); 11925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 12025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 12125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it2 = mTracks.begin(); 12225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it2 != it; ++it2) { 12325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber (*it2)->stop(); 12425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 12525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 12625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 12725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 12925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 13025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() { 13420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t max_duration = 0; 13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->stop(); 14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t duration = (*it)->getDuration(); 14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (duration > max_duration) { 14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber max_duration = duration; 14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fseek(mFile, mMdatOffset + 8, SEEK_SET); 15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t size = mOffset - mMdatOffset; 15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size = hton64(size); 15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&size, 1, 8, mFile); 15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fseek(mFile, mOffset, SEEK_SET); 15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 15720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("moov"); 15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("mvhd"); 16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // version=0, flags=0 16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // creation time 16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // modification time 16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(1000); // timescale 16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(max_duration); 16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // rate 16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0x100); // volume 16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0); // reserved 16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 17020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // matrix 17220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); 17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x40000000); 18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mTracks.size() + 1); // nextTrackID 18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // mvhd 18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t id = 1; 19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it, ++id) { 19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->writeTrackHeader(id); 19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // moov 19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1960c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fclose(mFile); 19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFile = NULL; 20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberoff_t MPEG4Writer::addSample(MediaBuffer *buffer) { 20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Mutex::Autolock autoLock(mLock); 20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t old_offset = mOffset; 20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1, buffer->range_length(), mFile); 20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21530ab66297501757d745b9ae10da61adcd891f497Andreas Huberoff_t MPEG4Writer::addLengthPrefixedSample(MediaBuffer *buffer) { 21630ab66297501757d745b9ae10da61adcd891f497Andreas Huber Mutex::Autolock autoLock(mLock); 21730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 21830ab66297501757d745b9ae10da61adcd891f497Andreas Huber off_t old_offset = mOffset; 21930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 22030ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 22130ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(length < 65536); 22230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 22330ab66297501757d745b9ae10da61adcd891f497Andreas Huber uint8_t x = length >> 8; 22430ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 22530ab66297501757d745b9ae10da61adcd891f497Andreas Huber x = length & 0xff; 22630ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 22730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 22830ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 22930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1, length, mFile); 23030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 23130ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset += length + 2; 23230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 23330ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 23430ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 23530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 2370c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.push_back(mOffset); 24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 2460c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset = *--mBoxes.end(); 24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fseek(mFile, offset, SEEK_SET); 25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mOffset - offset); 25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset -= 4; 25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fseek(mFile, mOffset, SEEK_SET); 25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&x, 1, 1, mFile); 25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++mOffset; 26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&x, 1, 2, mFile); 26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += 2; 26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&x, 1, 4, mFile); 27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += 4; 27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(&x, 1, 8, mFile); 27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += 8; 27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(s, 1, n + 1, mFile); 28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += n + 1; 28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 2880c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(s, 1, 4, mFile); 29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += 4; 29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite(data, 1, size, mFile); 29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += size; 29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 29925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 30025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 30125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 30225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 30325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 30425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 30525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 30625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 30725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 30825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 30925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 31025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 31425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber MPEG4Writer *owner, const sp<MediaSource> &source) 31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 31625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 32025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 32125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS(false) { 32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberstatus_t MPEG4Writer::Track::start() { 33425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber status_t err = mSource->start(); 33525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 33625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 33725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 33825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 33925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 34220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 34625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 34825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 35025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 35125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() { 35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource->stop(); 36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 36620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 36825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 36925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 37025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track->threadEntry(); 37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() { 38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> meta = mSource->getFormat(); 38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber meta->findCString(kKeyMIMEType, &mime); 38430ab66297501757d745b9ae10da61adcd891f497Andreas Huber bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4); 38530ab66297501757d745b9ae10da61adcd891f497Andreas Huber bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 38630ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (!mDone && mSource->read(&buffer) == OK) { 39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 39420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 39730ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 39830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 39930ab66297501757d745b9ae10da61adcd891f497Andreas Huber if (is_avc && count < 3) { 40030ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t size = buffer->range_length(); 40130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 40230ab66297501757d745b9ae10da61adcd891f497Andreas Huber switch (count) { 40330ab66297501757d745b9ae10da61adcd891f497Andreas Huber case 1: 40430ab66297501757d745b9ae10da61adcd891f497Andreas Huber { 40530ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK_EQ(mCodecSpecificData, NULL); 40630ab66297501757d745b9ae10da61adcd891f497Andreas Huber mCodecSpecificData = malloc(size + 8); 40730ab66297501757d745b9ae10da61adcd891f497Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 40830ab66297501757d745b9ae10da61adcd891f497Andreas Huber header[0] = 1; 40930ab66297501757d745b9ae10da61adcd891f497Andreas Huber header[1] = 0x42; // profile 41030ab66297501757d745b9ae10da61adcd891f497Andreas Huber header[2] = 0x80; 41130ab66297501757d745b9ae10da61adcd891f497Andreas Huber header[3] = 0x1e; // level 41230ab66297501757d745b9ae10da61adcd891f497Andreas Huber header[4] = 0xfc | 3; 41330ab66297501757d745b9ae10da61adcd891f497Andreas Huber header[5] = 0xe0 | 1; 41430ab66297501757d745b9ae10da61adcd891f497Andreas Huber header[6] = size >> 8; 41530ab66297501757d745b9ae10da61adcd891f497Andreas Huber header[7] = size & 0xff; 41630ab66297501757d745b9ae10da61adcd891f497Andreas Huber memcpy(&header[8], 41730ab66297501757d745b9ae10da61adcd891f497Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(), 41830ab66297501757d745b9ae10da61adcd891f497Andreas Huber size); 41930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 42030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mCodecSpecificDataSize = size + 8; 42130ab66297501757d745b9ae10da61adcd891f497Andreas Huber break; 42230ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 42330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 42430ab66297501757d745b9ae10da61adcd891f497Andreas Huber case 2: 42530ab66297501757d745b9ae10da61adcd891f497Andreas Huber { 42630ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t offset = mCodecSpecificDataSize; 42730ab66297501757d745b9ae10da61adcd891f497Andreas Huber mCodecSpecificDataSize += size + 3; 42830ab66297501757d745b9ae10da61adcd891f497Andreas Huber mCodecSpecificData = realloc(mCodecSpecificData, mCodecSpecificDataSize); 42930ab66297501757d745b9ae10da61adcd891f497Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 43030ab66297501757d745b9ae10da61adcd891f497Andreas Huber header[offset] = 1; 43130ab66297501757d745b9ae10da61adcd891f497Andreas Huber header[offset + 1] = size >> 8; 43230ab66297501757d745b9ae10da61adcd891f497Andreas Huber header[offset + 2] = size & 0xff; 43330ab66297501757d745b9ae10da61adcd891f497Andreas Huber memcpy(&header[offset + 3], 43430ab66297501757d745b9ae10da61adcd891f497Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(), 43530ab66297501757d745b9ae10da61adcd891f497Andreas Huber size); 43630ab66297501757d745b9ae10da61adcd891f497Andreas Huber break; 43730ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 43830ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 43930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 44030ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 44130ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 44230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 44330ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 44430ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 44530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData == NULL && is_mpeg4) { 44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *data = 44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const size_t size = buffer->range_length(); 45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t offset = 0; 45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (offset + 3 < size) { 45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (data[offset] == 0x00 && data[offset + 1] == 0x00 45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) { 45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++offset; 46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4620c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber // CHECK(offset + 3 < size); 463bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber if (offset + 3 >= size) { 464bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // XXX assume the entire first chunk of data is the codec specific 465bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // data. 466bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber offset = size; 467bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber } 46820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificDataSize = offset; 47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = malloc(offset); 47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber memcpy(mCodecSpecificData, data, offset); 47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->set_range(buffer->range_offset() + offset, size - offset); 47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 47630ab66297501757d745b9ae10da61adcd891f497Andreas Huber off_t offset = is_avc ? mOwner->addLengthPrefixedSample(buffer) 47730ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mOwner->addSample(buffer); 47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber SampleInfo info; 48030ab66297501757d745b9ae10da61adcd891f497Andreas Huber info.size = is_avc ? buffer->range_length() + 2 : buffer->range_length(); 48120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber info.offset = offset; 48220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 48348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int64_t timestampUs; 48448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); 48548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 48648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber // Our timestamp is in ms. 48748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber info.timestamp = (timestampUs + 500) / 1000; 48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 48920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSampleInfos.push_back(info); 49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 49120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 49220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 49320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 49425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 49525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 49820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberint64_t MPEG4Writer::Track::getDuration() const { 49920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return 10000; // XXX 50020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 50120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 50220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { 50320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 50420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findCString(kKeyMIMEType, &mime); 5050c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 50620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool is_audio = !strncasecmp(mime, "audio/", 6); 50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 51120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("trak"); 51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("tkhd"); 51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(trackID); 51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(getDuration()); 52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // layer 52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // alternate group 52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(is_audio ? 0x100 : 0); // volume 52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); // matrix 52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); 53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x40000000); 53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 5440c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 54620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(width); 54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(height); 54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // tkhd 55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdia"); 55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdhd"); 55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1000); // timescale 55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(getDuration()); 55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // language code XXX 56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("hdlr"); 56420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeFourcc(is_audio ? "soun" : "vide"); 56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeCString(""); // name 57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("minf"); 57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("dinf"); 57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("dref"); 57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); 57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("url "); 58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); // version=0, flags=1 58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // url 58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // dref 58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // dinf 58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("smhd"); 58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // balance 58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("vmhd"); 59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x00000001); // version=0, flags=1 59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // graphics mode 59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // opcolor 59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // minf 60120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stbl"); 60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsd"); 60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); // entry count 60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 60825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber const char *fourcc = NULL; 60918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 61025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "samr"; 61118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 61225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "sawb"; 61325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } else { 61425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 61525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber CHECK(!"should not be here, unknown mime type."); 61625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 61725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 61825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mOwner->beginBox(fourcc); // audio format 61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // data ref index 62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(2); // channel count 62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(16); // sample size 62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t samplerate; 63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 6310c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(samplerate << 16); 63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 63618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mp4v"); 63818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 63920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("s263"); 64030ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 64130ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avc1"); 64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 64325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 6440c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!"should not be here, unknown mime type."); 64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // data ref index 65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 65420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 6590c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(width); 66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(height); 66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // horiz resolution 66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // vert resolution 66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(1); // frame count 66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(" ", 32); 66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x18); // depth 66920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(-1); // predefined 67020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6710c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(23 + mCodecSpecificDataSize < 128); 67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 67318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 67420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("esds"); 67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 67820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x03); // ES_DescrTag 67920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(23 + mCodecSpecificDataSize); 68020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x0000); // ES_ID 68120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x1f); 68220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 68320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x04); // DecoderConfigDescrTag 68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(15 + mCodecSpecificDataSize); 68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x11); // streamType VisualStream 68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData[] = { 68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 0x77, 0x00, 69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00, 69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00 69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 69320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData, sizeof(kData)); 69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 69520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 69620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 69720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(mCodecSpecificDataSize); 69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 69920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData2[] = { 70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x06, // SLConfigDescriptorTag 70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x02 70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData2, sizeof(kData2)); 70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // esds 70818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("d263"); 71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // vendor 71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // decoder version 71320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(10); // level: 10 71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // profile: 0 71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // d263 71730ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 71830ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avcC"); 71930ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 72030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // avcC 72120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 72230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 72330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // mp4v, s263 or avc1 72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsd 72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 72720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stts"); 72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(mSampleInfos.size() - 1); 73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber List<SampleInfo>::iterator it = mSampleInfos.begin(); 73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t last = (*it).timestamp; 73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++it; 73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (it != mSampleInfos.end()) { 73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); 73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32((*it).timestamp - last); 73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber last = (*it).timestamp; 73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++it; 74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stts 74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsz"); 74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // default sample size 74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(mSampleInfos.size()); 74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mSampleInfos.end(); ++it) { 75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32((*it).size); 75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsz 75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsc"); 75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(mSampleInfos.size()); 75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t n = 1; 75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mSampleInfos.end(); ++it, ++n) { 76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(n); 76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); 76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); 76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsc 76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("co64"); 76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(mSampleInfos.size()); 76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mSampleInfos.end(); ++it, ++n) { 77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt64((*it).offset); 77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // co64 77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stbl 77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // mdia 77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // trak 77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 781