MPEG4Writer.cpp revision 215381ea729086b8359b7f59bdc2bd7cf55a0c45
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/* 220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project 320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License. 620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at 720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software 1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and 1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License. 1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */ 1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0 18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "MPEG4Writer" 19050b28a593350047845a45a14cc5026221ac1620James Dong#include <utils/Log.h> 20050b28a593350047845a45a14cc5026221ac1620James Dong 2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h> 2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h> 2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h> 2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h> 3018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 3103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h> 3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 34d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h> 35365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h> 3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 4125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track(MPEG4Writer *owner, const sp<MediaSource> &source); 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void stop(); 46a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong void pause(); 4725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 493b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 50d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 511acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong void writeTrackHeader(int32_t trackID, bool use32BitOffset = true); 5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 56693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 58a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 59a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 603b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t mMaxTimeStampUs; 61d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber struct SampleInfo { 6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t size; 6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t timestamp; 6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 6913aec890216948b0c364f8f92792129d0335f506James Dong List<SampleInfo> mSampleInfos; 70be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong bool mSamplesHaveSameSize; 71be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 7213aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 7313aec890216948b0c364f8f92792129d0335f506James Dong List<off_t> mChunkOffsets; 7413aec890216948b0c364f8f92792129d0335f506James Dong 7513aec890216948b0c364f8f92792129d0335f506James Dong struct StscTableEntry { 7613aec890216948b0c364f8f92792129d0335f506James Dong 7713aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 7813aec890216948b0c364f8f92792129d0335f506James Dong : firstChunk(chunk), 7913aec890216948b0c364f8f92792129d0335f506James Dong samplesPerChunk(samples), 8013aec890216948b0c364f8f92792129d0335f506James Dong sampleDescriptionId(id) {} 8113aec890216948b0c364f8f92792129d0335f506James Dong 8213aec890216948b0c364f8f92792129d0335f506James Dong uint32_t firstChunk; 8313aec890216948b0c364f8f92792129d0335f506James Dong uint32_t samplesPerChunk; 8413aec890216948b0c364f8f92792129d0335f506James Dong uint32_t sampleDescriptionId; 8513aec890216948b0c364f8f92792129d0335f506James Dong }; 8613aec890216948b0c364f8f92792129d0335f506James Dong List<StscTableEntry> mStscTableEntries; 8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 88050b28a593350047845a45a14cc5026221ac1620James Dong List<int32_t> mStssTableEntries; 89365a963142093a1cd8efdcea76b5f65096a5b115James Dong List<int64_t> mChunkDurations; 90050b28a593350047845a45a14cc5026221ac1620James Dong 91be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong struct SttsTableEntry { 92be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 93be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong SttsTableEntry(uint32_t count, uint32_t duration) 94be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong : sampleCount(count), sampleDuration(duration) {} 95be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 96be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t sampleCount; 97be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t sampleDuration; 98be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong }; 99be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SttsTableEntry> mSttsTableEntries; 100be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 103548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 10493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 1073c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 10893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 10993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 11093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t mTrackEveryNumberOfFrames; 11125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void threadEntry(); 11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t makeAVCCodecSpecificData( 11603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size); 11713aec890216948b0c364f8f92792129d0335f506James Dong void writeOneChunk(bool isAvc); 118215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 119215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 12093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void trackProgressStatus(int32_t nFrames, int64_t timeUs); 12193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 12203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 123215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Utilities for collecting statistical data 124215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong void logStatisticalData(bool isAudio); 125215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong void findMinAvgMaxSampleDurationMs( 126215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t *min, int32_t *avg, int32_t *max); 127215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong void findMinMaxChunkDurations(int64_t *min, int64_t *max); 128215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 12920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR 1 13403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 13520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFile(fopen(filename, "wb")), 1371acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 138a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 139a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 14113aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1427837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 14313aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs(500000) { 1440c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mFile != NULL); 14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14730ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 14830ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mFile(fdopen(fd, "wb")), 1491acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 150a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 151a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 15230ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 15313aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1547837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 15513aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs(500000) { 15630ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(mFile != NULL); 15730ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 15830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 15920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1692dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 17025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track *track = new Track(this, source); 17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 1722dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 1732dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 177a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 178a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 17993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 180a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 181a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 182a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 183a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 184a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 185a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 186a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 187a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 188a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 189a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 190a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 191a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 192a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1932dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 1942dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 1952dec2b5be2056c6d9428897dc672185872d30d17James Dong // 1962dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 1972dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 1982dec2b5be2056c6d9428897dc672185872d30d17James Dong // Currently, lets set to 0.4% for now. 1992dec2b5be2056c6d9428897dc672185872d30d17James Dong 2002dec2b5be2056c6d9428897dc672185872d30d17James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB, 2012dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 2022dec2b5be2056c6d9428897dc672185872d30d17James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 4 2032dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 2042dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 2052dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 2062dec2b5be2056c6d9428897dc672185872d30d17James Dong 2072dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 2082dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 2092dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 2102dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024; // 4 KB 2112dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 2122dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 2132dec2b5be2056c6d9428897dc672185872d30d17James Dong 2142dec2b5be2056c6d9428897dc672185872d30d17James Dong if (mMaxFileSizeLimitBytes != 0) { 2152dec2b5be2056c6d9428897dc672185872d30d17James Dong size = mMaxFileSizeLimitBytes * 4 / 1000; 2162dec2b5be2056c6d9428897dc672185872d30d17James Dong } else if (mMaxFileDurationLimitUs != 0) { 2172dec2b5be2056c6d9428897dc672185872d30d17James Dong if (bitRate <= 0) { 2182dec2b5be2056c6d9428897dc672185872d30d17James Dong // We could not estimate the file size since bitRate is not set. 2192dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 2202dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 2212dec2b5be2056c6d9428897dc672185872d30d17James Dong size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000); 2222dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2232dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2242dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 2252dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 2262dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2272dec2b5be2056c6d9428897dc672185872d30d17James Dong 2282dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 2292dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 2302dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 2312dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 2322dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2332dec2b5be2056c6d9428897dc672185872d30d17James Dong 2342dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 2352dec2b5be2056c6d9428897dc672185872d30d17James Dong " moov size %lld bytes", 2362dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 2372dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 2382dec2b5be2056c6d9428897dc672185872d30d17James Dong} 2392dec2b5be2056c6d9428897dc672185872d30d17James Dong 2402dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 24225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2452dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 2462dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 2472dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 2482dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 2492dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 2502dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2512dec2b5be2056c6d9428897dc672185872d30d17James Dong 2522dec2b5be2056c6d9428897dc672185872d30d17James Dong // System property can overwrite the file offset bits parameter 2532dec2b5be2056c6d9428897dc672185872d30d17James Dong char value[PROPERTY_VALUE_MAX]; 2542dec2b5be2056c6d9428897dc672185872d30d17James Dong if (property_get("media.stagefright.record-64bits", value, NULL) 2552dec2b5be2056c6d9428897dc672185872d30d17James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 2562dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 2572dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2582dec2b5be2056c6d9428897dc672185872d30d17James Dong 259065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 26093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 261a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 262a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 263a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 26493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 265a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 266a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 267a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 268a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2697837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = true; 2707837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 2717837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 2727837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 2737837c17063a4c50bc856ba59418516fdab731de7James Dong 27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("ftyp"); 27593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 27693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t fileType; 27793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (param && param->findInt32(kKeyFileType, &fileType) && 27893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong fileType != OUTPUT_FORMAT_MPEG_4) { 27993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("3gp4"); 28093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } else { 28193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("isom"); 28293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 28393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 28693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("3gp4"); 28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); 28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2897837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2917837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 2922dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 2932dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 2942dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 2952dec2b5be2056c6d9428897dc672185872d30d17James Dong } 2962dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 2977837c17063a4c50bc856ba59418516fdab731de7James Dong } 2987837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mEstimatedMoovBoxSize >= 8); 2997837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 3007837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize); 3017837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 3027837c17063a4c50bc856ba59418516fdab731de7James Dong 3037837c17063a4c50bc856ba59418516fdab731de7James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 3047837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 3057837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 3061acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 3071acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 3081acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 3091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 3101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 31193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = startTracks(param); 312a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 313a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 315a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 31625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 319a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::pause() { 320a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mFile == NULL) { 321a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return; 322a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 323a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 324a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 325a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 326a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it)->pause(); 327a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 328a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 329a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::stop() { 33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t max_duration = 0; 33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*it)->stop(); 33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3403b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t duration = (*it)->getDurationUs(); 34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (duration > max_duration) { 34220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber max_duration = duration; 34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3467837c17063a4c50bc856ba59418516fdab731de7James Dong 34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 3481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 3491acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 3501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 3511acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fwrite(&size, 1, 4, mFile); 3521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 3531acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fseeko(mFile, mMdatOffset + 8, SEEK_SET); 3541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int64_t size = mOffset - mMdatOffset; 3551acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 3561acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fwrite(&size, 1, 8, mFile); 3571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 3587837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 3617837c17063a4c50bc856ba59418516fdab731de7James Dong const off_t moovOffset = mOffset; 3627837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = true; 3637837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 3647837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 3657837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 3661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t timeScale = 1000; 3671acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t duration = max_duration / timeScale; 36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("moov"); 37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("mvhd"); 37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // version=0, flags=0 37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // creation time 37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // modification time 3751acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(timeScale); // timescale 3761acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(duration); 3771acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(0x10000); // rate: 1.0 37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0x100); // volume 37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0); // reserved 38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // matrix 38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 38420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); 38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x40000000); 39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 39420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 39720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mTracks.size() + 1); // nextTrackID 39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // mvhd 39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t id = 1; 40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it, ++id) { 4031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong (*it)->writeTrackHeader(id, mUse32BitOffset); 40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 40520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // moov 40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4077837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 4087837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 4097837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 4107837c17063a4c50bc856ba59418516fdab731de7James Dong 4117837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 4127837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 4137837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 4147837c17063a4c50bc856ba59418516fdab731de7James Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); 4157837c17063a4c50bc856ba59418516fdab731de7James Dong 4167837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 4172dec2b5be2056c6d9428897dc672185872d30d17James Dong fseeko(mFile, mOffset, SEEK_SET); 4187837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 4197837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 4207837c17063a4c50bc856ba59418516fdab731de7James Dong 4217837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 4227837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 4237837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 4247837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 4252dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 4262dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("The mp4 file will not be streamable."); 4277837c17063a4c50bc856ba59418516fdab731de7James Dong } 4287837c17063a4c50bc856ba59418516fdab731de7James Dong 4290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4317837c17063a4c50bc856ba59418516fdab731de7James Dong fflush(mFile); 43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fclose(mFile); 43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFile = NULL; 434a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = false; 43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 43713aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 43813aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 43913aec890216948b0c364f8f92792129d0335f506James Dong return OK; 44013aec890216948b0c364f8f92792129d0335f506James Dong} 44113aec890216948b0c364f8f92792129d0335f506James Dong 44213aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 44313aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 44413aec890216948b0c364f8f92792129d0335f506James Dong} 44513aec890216948b0c364f8f92792129d0335f506James Dong 44613aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 44713aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 44813aec890216948b0c364f8f92792129d0335f506James Dong} 44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45013aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t old_offset = mOffset; 45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1, buffer->range_length(), mFile); 45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 46103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 46203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 46303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 46403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 46503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 46603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 46703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 46803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 46903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 47003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 47103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 47203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 47303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 47403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 47513aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 47630ab66297501757d745b9ae10da61adcd891f497Andreas Huber off_t old_offset = mOffset; 47730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 47830ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 47903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 48003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 48103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t x = length >> 24; 48203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 48303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 16) & 0xff; 48403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 48503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 8) & 0xff; 48603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 48703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = length & 0xff; 48803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 48903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 49030ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(length < 65536); 49130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 49230ab66297501757d745b9ae10da61adcd891f497Andreas Huber uint8_t x = length >> 8; 49330ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 49430ab66297501757d745b9ae10da61adcd891f497Andreas Huber x = length & 0xff; 49530ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 49603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 49730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 49830ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 49930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1, length, mFile); 50030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 50103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 50203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mOffset += length + 4; 50303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 50430ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset += length + 2; 50503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 50630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 50730ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 50830ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 50930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 5107837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 5117837c17063a4c50bc856ba59418516fdab731de7James Dong const void *ptr, size_t size, size_t nmemb, FILE *stream) { 5127837c17063a4c50bc856ba59418516fdab731de7James Dong 5137837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 5147837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 5151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 5161acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 5177837c17063a4c50bc856ba59418516fdab731de7James Dong for (List<off_t>::iterator it = mBoxes.begin(); 5187837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 5197837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 5207837c17063a4c50bc856ba59418516fdab731de7James Dong } 5217837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 5227837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); 5237837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 5247837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 5257837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 5267837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 5277837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 5287837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 5297837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = false; 5307837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 5317837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 5327837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 5337837c17063a4c50bc856ba59418516fdab731de7James Dong } 5347837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 5357837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 5367837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 5377837c17063a4c50bc856ba59418516fdab731de7James Dong } 5387837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 5397837c17063a4c50bc856ba59418516fdab731de7James Dong} 5407837c17063a4c50bc856ba59418516fdab731de7James Dong 54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 5420c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5447837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 5457837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 54620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 5520c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset = *--mBoxes.end(); 55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5577837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 5587837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 5597837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 5607837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 5617837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, offset, SEEK_SET); 5627837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 5637837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 5647837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 5657837c17063a4c50bc856ba59418516fdab731de7James Dong } 56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 5697837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 1, mFile); 57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 5747837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 2, mFile); 57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 5797837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 4, mFile); 58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 5847837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 8, mFile); 58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 5897837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, n + 1, mFile); 59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 5930c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 5947837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, 4, mFile); 59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 5987837c17063a4c50bc856ba59418516fdab731de7James Dong write(data, 1, size, mFile); 59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 601d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 602d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 603d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 604d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 605d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 606d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 607956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 608d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 609d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 610d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 611d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 612d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes); 613d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 614d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 615d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 616d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 617d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 618d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 619d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 620d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 621d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 622d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 623d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 624d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 625d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 626d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 627d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 628d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 629d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 63025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 63125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 63225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 63325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 63425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 63525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 63625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 63725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 63825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 63925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 64025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 64125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 64225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 643f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 644f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("setStartTimestampUs: %lld", timeUs); 645f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong CHECK(timeUs >= 0); 6463c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 647065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 648f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 649f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("Earliest track starting time: %lld", mStartTimestampUs); 6503c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 6513c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 6523c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 653f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 654f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("getStartTimestampUs: %lld", mStartTimestampUs); 6553c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 6563c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 6573c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 6583c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 65958ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 66058ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 66158ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 66258ae9c530247668f8af36e30d228c716c226b3d4James Dong} 66358ae9c530247668f8af36e30d228c716c226b3d4James Dong 66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 66620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 66725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber MPEG4Writer *owner, const sp<MediaSource> &source) 66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 66925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 67020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 67120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 672a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 673a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 6743b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs(0), 675956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 676be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 67825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 679548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 68025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS(false) { 68120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 68220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 68320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 69293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 69393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("initTrackingProgressStatus"); 69493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 69593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 69693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 69793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryNumberOfFrames = 0; 69893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 69993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 70093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 70193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Receive request to track progress status for every %lld us", timeUs); 70293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 70393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 70493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 70593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 70693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 70793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t nFrames; 70893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt32(kKeyTrackFrameStatus, &nFrames)) { 70993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Receive request to track progress status for every %d frames", nFrames); 71093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryNumberOfFrames = nFrames; 71193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 71293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 71393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 71493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 71593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 71693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 717a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 718a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 719a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 720a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 721a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 72225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 72393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 72493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong CHECK(params && params->findInt64(kKeyTime, &startTimeUs)); 72593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 72693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 727f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 728f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 729f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 73025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 73125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 73225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 73325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 7403b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs = 0; 74125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 742956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 74625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 74725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 750a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongvoid MPEG4Writer::Track::pause() { 751a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 752a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 753a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::stop() { 75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return; 75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource->stop(); 76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 76825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 76925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 77025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track->threadEntry(); 77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 780548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h> 781548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) { 782548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber const uint8_t *data = (const uint8_t *)_data; 783548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t offset = 0; 784548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber while (offset < size) { 785548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("0x%04x ", offset); 786548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 787548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t n = size - offset; 788548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (n > 16) { 789548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber n = 16; 790548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 791548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 792548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < 16; ++i) { 793548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (i == 8) { 794548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 795548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 796548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 797548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (offset + i < size) { 798548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%02x ", data[offset + i]); 799548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 800548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 801548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 802548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 803548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 804548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 805548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 806548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < n; ++i) { 807548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (isprint(data[offset + i])) { 808548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%c", data[offset + i]); 809548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 810548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("."); 811548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 812548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 813548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 814548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("\n"); 815548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 816548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber offset += 16; 817548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 818548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber} 819548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 820548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 82103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 82203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 823548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber // hexdump(data, size); 824548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 82503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 826548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Already have codec specific data"); 82703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 82803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 82903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 83003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) { 831548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Must start with a start code"); 83203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 83303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 83403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 83503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamOffset = 4; 83603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber while (picParamOffset + 3 < size 83703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) { 83803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber ++picParamOffset; 83903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 84003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 84103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (picParamOffset + 3 >= size) { 842548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Could not find start-code for pictureParameterSet"); 84303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 84403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 84503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 84603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t seqParamSetLength = picParamOffset - 4; 84703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t picParamSetLength = size - picParamOffset - 4; 84803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 84903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 85003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2; 85103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 85203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 85303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 85403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 85503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = 0x42; // profile 85603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = 0x80; 85703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[3] = 0x1e; // level 85803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 85903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 86003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 3; // length size == 4 bytes 86103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 86203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 1; // length size == 2 bytes 86303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 86403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 86503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[5] = 0xe0 | 1; 86603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[6] = seqParamSetLength >> 8; 86703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[7] = seqParamSetLength & 0xff; 86803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[8], &data[4], seqParamSetLength); 86903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header += 8 + seqParamSetLength; 87003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[0] = 1; 87103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[1] = picParamSetLength >> 8; 87203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[2] = picParamSetLength & 0xff; 87303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength); 87403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 87503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 87603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 87703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 87820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::Track::threadEntry() { 87920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> meta = mSource->getFormat(); 88020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 88120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber meta->findCString(kKeyMIMEType, &mime); 882050b28a593350047845a45a14cc5026221ac1620James Dong bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 883050b28a593350047845a45a14cc5026221ac1620James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 88430ab66297501757d745b9ae10da61adcd891f497Andreas Huber bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 885956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong bool is_audio = !strncasecmp(mime, "audio/", 6); 88630ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 88713aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 88813aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 88913aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 89013aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 891be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong int64_t lastTimestamp = 0; // Timestamp of the previous sample 892be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong int64_t lastDuration = 0; // Time spacing between the previous two samples 893be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 894be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 895a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 896d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 89720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 89893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 90093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 90120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 90220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 90320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 90413aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 908a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 909a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 910a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 911a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 912a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 913a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 914a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 915a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 916a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 91730ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 91830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 91903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 92003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 92103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 922548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 923548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 92403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (is_avc) { 92503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 92603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 92703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 92803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 929be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 93003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } else if (is_mpeg4) { 93103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 93203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 93303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 93403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 93503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 93603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 93730ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 93830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 93930ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 94030ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 94130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 942548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 94330ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 944548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && 945548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber count == 1 && is_mpeg4 && mCodecSpecificData == NULL) { 94603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI mpeg4 encoder does not properly set the 94703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // codec-specific-data flag. 94830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *data = 95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const size_t size = buffer->range_length(); 95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t offset = 0; 95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (offset + 3 < size) { 95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (data[offset] == 0x00 && data[offset + 1] == 0x00 95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) { 95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 96120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++offset; 96220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9640c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber // CHECK(offset + 3 < size); 965bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber if (offset + 3 >= size) { 966bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // XXX assume the entire first chunk of data is the codec specific 967bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber // data. 968bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber offset = size; 969bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber } 97020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 97120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificDataSize = offset; 97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = malloc(offset); 97320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber memcpy(mCodecSpecificData, data, offset); 97420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->set_range(buffer->range_offset() + offset, size - offset); 97603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 97703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (size == offset) { 97803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 97903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 98003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 98103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 98203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 983548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 984548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 985548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else if (!mGotAllCodecSpecificData && is_avc && count < 3) { 98603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // The TI video encoder does not flag codec specific data 98703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber // as such and also splits up SPS and PPS across two buffers. 98803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 98903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data = 99003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 99103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 99203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t size = buffer->range_length(); 99303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 99403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber CHECK(count == 2 || mCodecSpecificData == NULL); 99503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 99603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size_t offset = mCodecSpecificDataSize; 99703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize += size + 4; 99803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = 99903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber realloc(mCodecSpecificData, mCodecSpecificDataSize); 100003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 100103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset, 100203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber "\x00\x00\x00\x01", 4); 100303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 100403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size); 100503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 100603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->release(); 100703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer = NULL; 100803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 100903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (count == 2) { 101003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber void *tmp = mCodecSpecificData; 101103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber size = mCodecSpecificDataSize; 101203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = NULL; 101303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = 0; 101403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 101503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 101603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)tmp, size); 101703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber free(tmp); 101803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber tmp = NULL; 1019be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 1020548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1021548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 102203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 102303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 102403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber continue; 102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1027a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mGotAllCodecSpecificData) { 1028a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mGotAllCodecSpecificData = true; 1029a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1030a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1031d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 1032d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 1033d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 1034d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 1035d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 1036d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 1037d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 1038d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 1039d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 1040d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1041d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (is_avc) StripStartcode(copy); 1042e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 104320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber SampleInfo info; 104403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber info.size = is_avc 104503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 1046d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong ? copy->range_length() + 4 104703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 1048d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong ? copy->range_length() + 2 104903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 1050d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong : copy->range_length(); 1051050b28a593350047845a45a14cc5026221ac1620James Dong 1052d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 1053d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mEstimatedTrackSizeBytes += info.size; 1054d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 1055d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 1056d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1057d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1058d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 1059d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 1060d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1061d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1062d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1063050b28a593350047845a45a14cc5026221ac1620James Dong 1064d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 1065d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 1066d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 106748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int64_t timestampUs; 1068d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 1069d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1070d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 10713c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong if (mSampleInfos.empty()) { 1072f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 1073f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 10743c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 107548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 1076a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 1077a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - 1000 * lastDuration); 1078a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 1079a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1080a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1081a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 1082a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong LOGV("time stamp: %lld and previous paused duration %lld", 1083a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs, previousPausedDurationUs); 10843b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber if (timestampUs > mMaxTimeStampUs) { 10853b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber mMaxTimeStampUs = timestampUs; 10863b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 10873b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 108848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber // Our timestamp is in ms. 108948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber info.timestamp = (timestampUs + 500) / 1000; 109020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSampleInfos.push_back(info); 1091be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() > 2) { 1092be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (lastDuration != info.timestamp - lastTimestamp) { 1093be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong SttsTableEntry sttsEntry(sampleCount, lastDuration); 1094be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSttsTableEntries.push_back(sttsEntry); 1095be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 1096be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1097be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 1098be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1099be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1100be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 1101be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() >= 2 && previousSampleSize != info.size) { 1102be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 1103be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1104be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong previousSampleSize = info.size; 1105be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1106be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong lastDuration = info.timestamp - lastTimestamp; 1107be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong lastTimestamp = info.timestamp; 110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1109d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 1110d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong mStssTableEntries.push_back(mSampleInfos.size()); 1111d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 1112d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 111393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 111493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 111593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 111693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 111793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong trackProgressStatus(mSampleInfos.size(), timestampUs); 111893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 111958ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mOwner->numTracks() == 1) { 112058ae9c530247668f8af36e30d228c716c226b3d4James Dong off_t offset = is_avc? mOwner->addLengthPrefixedSample_l(copy) 112158ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 112258ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mChunkOffsets.empty()) { 112358ae9c530247668f8af36e30d228c716c226b3d4James Dong mChunkOffsets.push_back(offset); 112458ae9c530247668f8af36e30d228c716c226b3d4James Dong } 112558ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 112658ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 112758ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 112858ae9c530247668f8af36e30d228c716c226b3d4James Dong } 112913aec890216948b0c364f8f92792129d0335f506James Dong 113013aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 113113aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 113213aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(++nChunks, 1, 1); 113313aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 113413aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 113513aec890216948b0c364f8f92792129d0335f506James Dong } else { 113613aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 113713aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 113813aec890216948b0c364f8f92792129d0335f506James Dong } else { 113913aec890216948b0c364f8f92792129d0335f506James Dong if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 114013aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 1141365a963142093a1cd8efdcea76b5f65096a5b115James Dong mChunkDurations.push_back(timestampUs - chunkTimestampUs); 114213aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 114313aec890216948b0c364f8f92792129d0335f506James Dong (--(mStscTableEntries.end()))->samplesPerChunk != 114413aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size()) { 114513aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(nChunks, 114613aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size(), 1); 114713aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 114813aec890216948b0c364f8f92792129d0335f506James Dong } 114913aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 115013aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 115113aec890216948b0c364f8f92792129d0335f506James Dong } 115213aec890216948b0c364f8f92792129d0335f506James Dong } 115313aec890216948b0c364f8f92792129d0335f506James Dong } 115413aec890216948b0c364f8f92792129d0335f506James Dong 115520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 115625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1157f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong if (mSampleInfos.empty()) { 115893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong err = UNKNOWN_ERROR; 1159f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 116093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_COMPLETION_STATUS, err); 1161be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 116213aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 116358ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mOwner->numTracks() == 1) { 116458ae9c530247668f8af36e30d228c716c226b3d4James Dong StscTableEntry stscEntry(1, mSampleInfos.size(), 1); 116558ae9c530247668f8af36e30d228c716c226b3d4James Dong mStscTableEntries.push_back(stscEntry); 116658ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 116713aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 116813aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1); 116913aec890216948b0c364f8f92792129d0335f506James Dong mStscTableEntries.push_back(stscEntry); 117013aec890216948b0c364f8f92792129d0335f506James Dong writeOneChunk(is_avc); 117113aec890216948b0c364f8f92792129d0335f506James Dong } 117213aec890216948b0c364f8f92792129d0335f506James Dong 1173be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 1174be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 1175be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 1176be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSampleInfos.size() == 1) { 1177be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong lastDuration = 0; // A single sample's duration 1178be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1179be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 1180be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1181be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong SttsTableEntry sttsEntry(sampleCount, lastDuration); 1182be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSttsTableEntries.push_back(sttsEntry); 118325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 1184956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s", 1185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong count, nZeroLengthFrames, mSampleInfos.size(), is_audio? "audio": "video"); 1186365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1187365a963142093a1cd8efdcea76b5f65096a5b115James Dong logStatisticalData(is_audio); 1188365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1189365a963142093a1cd8efdcea76b5f65096a5b115James Dong 119093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::trackProgressStatus(int32_t nFrames, int64_t timeUs) { 119193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("trackProgressStatus: %d frames and %lld us", nFrames, timeUs); 1192215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryNumberOfFrames > 0 && 1193215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong nFrames % mTrackEveryNumberOfFrames == 0) { 119493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Fire frame tracking progress status at frame %d", nFrames); 119593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, 119693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong MEDIA_RECORDER_INFO_PROGRESS_FRAME_STATUS, 119793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong nFrames); 119893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 119993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1200215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 1201215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 120293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Fire time tracking progress status at %lld us", timeUs); 120393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, 120493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS, 120593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong timeUs / 1000); 120693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 120793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 120893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 120993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1210215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dongvoid MPEG4Writer::Track::findMinAvgMaxSampleDurationMs( 1211215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t *min, int32_t *avg, int32_t *max) { 1212215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(!mSampleInfos.empty()); 1213215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t avgSampleDurationMs = mMaxTimeStampUs / 1000/ mSampleInfos.size(); 1214215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t minSampleDurationMs = 0x7FFFFFFF; 1215215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t maxSampleDurationMs = 0; 1216365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1217365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != mSttsTableEntries.end(); ++it) { 1218215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t sampleDurationMs = static_cast<int32_t>(it->sampleDuration); 1219215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (sampleDurationMs > maxSampleDurationMs) { 1220215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong maxSampleDurationMs = sampleDurationMs; 1221215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong } else if (sampleDurationMs < minSampleDurationMs) { 1222215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong minSampleDurationMs = sampleDurationMs; 1223365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1224215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong LOGI("sample duration: %d ms", sampleDurationMs); 1225365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1226215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(minSampleDurationMs != 0); 1227215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(avgSampleDurationMs != 0); 1228215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(maxSampleDurationMs != 0); 1229215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong *min = minSampleDurationMs; 1230215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong *avg = avgSampleDurationMs; 1231215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong *max = maxSampleDurationMs; 1232365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1233365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1234365a963142093a1cd8efdcea76b5f65096a5b115James Dong// Don't count the last duration 1235365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) { 1236365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t duration = mOwner->interleaveDuration(); 1237365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t minChunkDuration = duration; 1238365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t maxChunkDuration = duration; 1239365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (mChunkDurations.size() > 1) { 1240365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<int64_t>::iterator it = mChunkDurations.begin(); 1241365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != --mChunkDurations.end(); ++it) { 1242365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (minChunkDuration > (*it)) { 1243365a963142093a1cd8efdcea76b5f65096a5b115James Dong minChunkDuration = (*it); 1244365a963142093a1cd8efdcea76b5f65096a5b115James Dong } else if (maxChunkDuration < (*it)) { 1245365a963142093a1cd8efdcea76b5f65096a5b115James Dong maxChunkDuration = (*it); 1246365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1247365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1248365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1249365a963142093a1cd8efdcea76b5f65096a5b115James Dong *min = minChunkDuration; 1250365a963142093a1cd8efdcea76b5f65096a5b115James Dong *max = maxChunkDuration; 1251365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1252365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1253365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::logStatisticalData(bool isAudio) { 1254365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (mMaxTimeStampUs <= 0 || mSampleInfos.empty()) { 1255365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("nothing is recorded"); 1256365a963142093a1cd8efdcea76b5f65096a5b115James Dong return; 1257365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1258365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1259365a963142093a1cd8efdcea76b5f65096a5b115James Dong bool collectStats = false; 1260365a963142093a1cd8efdcea76b5f65096a5b115James Dong char value[PROPERTY_VALUE_MAX]; 1261365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (property_get("media.stagefright.record-stats", value, NULL) 1262365a963142093a1cd8efdcea76b5f65096a5b115James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 1263365a963142093a1cd8efdcea76b5f65096a5b115James Dong collectStats = true; 1264365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1265365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1266365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (collectStats) { 1267215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong LOGI("%s track - duration %lld us, total %d frames", 1268215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong isAudio? "audio": "video", mMaxTimeStampUs, 1269215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong mSampleInfos.size()); 1270215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t min, avg, max; 1271215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong findMinAvgMaxSampleDurationMs(&min, &avg, &max); 1272215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max); 1273215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (!isAudio) { 1274215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong float avgFps = 1000.0 / avg; 1275215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong float minFps = 1000.0 / max; 1276215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong float maxFps = 1000.0 / min; 1277365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f", 1278215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong minFps, avgFps, maxFps); 1279365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1280365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1281365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t totalBytes = 0; 1282365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 1283365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != mSampleInfos.end(); ++it) { 1284365a963142093a1cd8efdcea76b5f65096a5b115James Dong totalBytes += it->size; 1285365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1286365a963142093a1cd8efdcea76b5f65096a5b115James Dong float bitRate = (totalBytes * 8000000.0) / mMaxTimeStampUs; 1287365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("avg bit rate (bps): %.2f", bitRate); 1288365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1289365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t duration = mOwner->interleaveDuration(); 1290365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (duration != 0) { // If interleaving is enabled 1291365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t minChunk, maxChunk; 1292365a963142093a1cd8efdcea76b5f65096a5b115James Dong findMinMaxChunkDurations(&minChunk, &maxChunk); 1293365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld", 1294365a963142093a1cd8efdcea76b5f65096a5b115James Dong minChunk, duration, maxChunk); 1295365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1296365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 129713aec890216948b0c364f8f92792129d0335f506James Dong} 129813aec890216948b0c364f8f92792129d0335f506James Dong 129913aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::Track::writeOneChunk(bool isAvc) { 130013aec890216948b0c364f8f92792129d0335f506James Dong mOwner->lock(); 130113aec890216948b0c364f8f92792129d0335f506James Dong for (List<MediaBuffer *>::iterator it = mChunkSamples.begin(); 130213aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkSamples.end(); ++it) { 130313aec890216948b0c364f8f92792129d0335f506James Dong off_t offset = isAvc? mOwner->addLengthPrefixedSample_l(*it) 130413aec890216948b0c364f8f92792129d0335f506James Dong : mOwner->addSample_l(*it); 130513aec890216948b0c364f8f92792129d0335f506James Dong if (it == mChunkSamples.begin()) { 130613aec890216948b0c364f8f92792129d0335f506James Dong mChunkOffsets.push_back(offset); 130713aec890216948b0c364f8f92792129d0335f506James Dong } 130813aec890216948b0c364f8f92792129d0335f506James Dong } 130913aec890216948b0c364f8f92792129d0335f506James Dong mOwner->unlock(); 131013aec890216948b0c364f8f92792129d0335f506James Dong while (!mChunkSamples.empty()) { 131113aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *>::iterator it = mChunkSamples.begin(); 131213aec890216948b0c364f8f92792129d0335f506James Dong (*it)->release(); 131313aec890216948b0c364f8f92792129d0335f506James Dong (*it) = NULL; 131413aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.erase(it); 131513aec890216948b0c364f8f92792129d0335f506James Dong } 131613aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13193b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 13203b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber return mMaxTimeStampUs; 132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1323d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 1324d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 1325d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1326d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 13271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader( 13281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t trackID, bool use32BitOffset) { 132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findCString(kKeyMIMEType, &mime); 13310c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool is_audio = !strncasecmp(mime, "audio/", 6); 13341acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t timeScale = 1000; 13351acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t duration = getDurationUs() / timeScale; 133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("trak"); 134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("tkhd"); 13421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Flags = 7 to indicate that the track is enabled, and 13431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // part of the presentation 13441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0x07); // version=0, flags=7 134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(trackID); 134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 13491acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(duration); 135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // layer 135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // alternate group 135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(is_audio ? 0x100 : 0); // volume 135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); // matrix 135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); 136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x40000000); 136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 13740c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 137520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1376050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 1377050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 137820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // tkhd 138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1381f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 1382f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (mStartTimestampUs != moovStartTimeUs) { 13833c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("edts"); 13843c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("elst"); 13851acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0); // version=0, flags=0: 32-bit time 13861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(2); // never ends with an empty list 1387f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t durationMs = 1388f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong (mStartTimestampUs - moovStartTimeUs) / 1000; 1389f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->writeInt32(durationMs); // edit duration 1390956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mOwner->writeInt32(-1); // empty edit box to signal starting time offset 13911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // x1 rate 13921acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(duration); 13931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0); 13941acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); 13953c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 13963c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 13973c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 13983c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdia"); 140020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 140120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdhd"); 140220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 140320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 140420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 14051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(timeScale); // timescale 14061acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(duration); // duration 14071acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Language follows the three letter standard ISO-639-2/T 14081acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // 'e', 'n', 'g' for "English", for instance. 14091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Each character is packed as the difference between its ASCII value and 0x60. 14101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // For "English", these are 00101, 01110, 00111. 14111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // XXX: Where is the padding bit located: 0x15C7? 14121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt16(0); // language code 141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 141420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("hdlr"); 141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1418050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // component type: should be mhlr 1419050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeFourcc(is_audio ? "soun" : "vide"); // component subtype 142020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 142120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 14231acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Removing "r" for the name string just makes the string 4 byte aligned 14241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeCString(is_audio ? "SoundHandle": "VideoHandle"); // name 142520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 142620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("minf"); 142820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("smhd"); 143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 143120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // balance 143220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 143520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("vmhd"); 14361acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0x01); // version=0, flags=1 143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // graphics mode 143820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // opcolor 143920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1443050b28a593350047845a45a14cc5026221ac1620James Dong 1444050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dinf"); 1445050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dref"); 1446050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 14471acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1); // entry count (either url or urn) 14481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // The table index here refers to the sample description index 14491acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // in the sample table entries. 1450050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("url "); 14511acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 1452050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // url 1453050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dref 1454050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dinf 1455050b28a593350047845a45a14cc5026221ac1620James Dong 145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stbl"); 145720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 145820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsd"); 145920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 146020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); // entry count 146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (is_audio) { 146225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber const char *fourcc = NULL; 146318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 146425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "samr"; 146518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 146625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "sawb"; 1467050b28a593350047845a45a14cc5026221ac1620James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1468050b28a593350047845a45a14cc5026221ac1620James Dong fourcc = "mp4a"; 146925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } else { 147025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 147125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber CHECK(!"should not be here, unknown mime type."); 147225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 147325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 147425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mOwner->beginBox(fourcc); // audio format 147520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 1477050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x1); // data ref index 147820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 147920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 1480050b28a593350047845a45a14cc5026221ac1620James Dong int32_t nChannels; 1481050b28a593350047845a45a14cc5026221ac1620James Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 1482050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(nChannels); // channel count 148320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(16); // sample size 148420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 148520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 148620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 148720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t samplerate; 148820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 14890c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 149020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(samplerate << 16); 1492050b28a593350047845a45a14cc5026221ac1620James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1493050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("esds"); 1494050b28a593350047845a45a14cc5026221ac1620James Dong 1495050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1496050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x03); // ES_DescrTag 1497050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 1498050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x0000);// ES_ID 1499050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); 1500050b28a593350047845a45a14cc5026221ac1620James Dong 1501050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 1502050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 1503050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 1504050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x15); // streamType AudioStream 1505050b28a593350047845a45a14cc5026221ac1620James Dong 1506050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x03); // XXX 1507050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); // buffer size 24-bit 1508050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // max bit rate 1509050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // avg bit rate 1510050b28a593350047845a45a14cc5026221ac1620James Dong 1511050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 1512050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(mCodecSpecificDataSize); 1513050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 1514050b28a593350047845a45a14cc5026221ac1620James Dong 1515050b28a593350047845a45a14cc5026221ac1620James Dong static const uint8_t kData2[] = { 1516050b28a593350047845a45a14cc5026221ac1620James Dong 0x06, // SLConfigDescriptorTag 1517050b28a593350047845a45a14cc5026221ac1620James Dong 0x01, 1518050b28a593350047845a45a14cc5026221ac1620James Dong 0x02 1519050b28a593350047845a45a14cc5026221ac1620James Dong }; 1520050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(kData2, sizeof(kData2)); 1521050b28a593350047845a45a14cc5026221ac1620James Dong 1522050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // esds 1523050b28a593350047845a45a14cc5026221ac1620James Dong } 152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 152618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mp4v"); 152818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("s263"); 153030ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 153130ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avc1"); 153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 153325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 15340c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!"should not be here, unknown mime type."); 153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 15391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt16(1); // data ref index 154020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 154120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 154220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 154320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 154420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 154520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 154620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 154720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 154820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 15490c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 155020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 155120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(width); 155220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(height); 155320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // horiz resolution 155420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // vert resolution 155520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 155620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(1); // frame count 155720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(" ", 32); 155820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x18); // depth 155920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(-1); // predefined 156020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15610c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(23 + mCodecSpecificDataSize < 128); 156220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 156318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 156420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("esds"); 156520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 156620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 156720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 156820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x03); // ES_DescrTag 156920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(23 + mCodecSpecificDataSize); 157020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x0000); // ES_ID 157120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x1f); 157220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 157320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x04); // DecoderConfigDescrTag 157420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(15 + mCodecSpecificDataSize); 157520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 157620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x11); // streamType VisualStream 157720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 157820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData[] = { 157920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 0x77, 0x00, 158020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00, 158120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00 158220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 158320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData, sizeof(kData)); 1584050b28a593350047845a45a14cc5026221ac1620James Dong 158520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 158620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 158720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(mCodecSpecificDataSize); 158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 158920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 159020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData2[] = { 159120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x06, // SLConfigDescriptorTag 159220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 159320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x02 159420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 159520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData2, sizeof(kData2)); 159620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 159720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // esds 159818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 159920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("d263"); 160020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 160120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // vendor 160220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // decoder version 160320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(10); // level: 10 160420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // profile: 0 160520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 160620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // d263 160730ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 160830ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avcC"); 160930ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 161030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // avcC 161120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 161230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 16131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->beginBox("pasp"); 16141acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // This is useful if the pixel is not square 16151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // hspacing 16161acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // vspacing 16171acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->endBox(); // pasp 161830ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // mp4v, s263 or avc1 161920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 162020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsd 162120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 162220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stts"); 162320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1624be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(mSttsTableEntries.size()); 1625be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1626be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSttsTableEntries.end(); ++it) { 1627be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleCount); 1628be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleDuration); 162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stts 163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1632050b28a593350047845a45a14cc5026221ac1620James Dong if (!is_audio) { 1633050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("stss"); 1634050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1635050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames 1636050b28a593350047845a45a14cc5026221ac1620James Dong for (List<int32_t>::iterator it = mStssTableEntries.begin(); 1637050b28a593350047845a45a14cc5026221ac1620James Dong it != mStssTableEntries.end(); ++it) { 1638050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(*it); 1639050b28a593350047845a45a14cc5026221ac1620James Dong } 1640050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // stss 1641050b28a593350047845a45a14cc5026221ac1620James Dong } 1642050b28a593350047845a45a14cc5026221ac1620James Dong 164320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsz"); 164420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1645be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 1646be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SampleInfo>::iterator it = mSampleInfos.begin(); 1647be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->size); // default sample size 1648be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1649be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(0); 1650be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 165120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(mSampleInfos.size()); 1652be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (!mSamplesHaveSameSize) { 1653be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 1654be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSampleInfos.end(); ++it) { 1655be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32((*it).size); 1656be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 165720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 165820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsz 165920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 166020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsc"); 166120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 166213aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(mStscTableEntries.size()); 166313aec890216948b0c364f8f92792129d0335f506James Dong for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 166413aec890216948b0c364f8f92792129d0335f506James Dong it != mStscTableEntries.end(); ++it) { 166513aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->firstChunk); 166613aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->samplesPerChunk); 166713aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->sampleDescriptionId); 166820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 166920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsc 16701acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 167120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 167213aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(mChunkOffsets.size()); 167313aec890216948b0c364f8f92792129d0335f506James Dong for (List<off_t>::iterator it = mChunkOffsets.begin(); 167413aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkOffsets.end(); ++it) { 16751acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (use32BitOffset) { 16761acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(static_cast<int32_t>(*it)); 16771acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 16781acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt64((*it)); 16791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 168020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 168120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // co64 168220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 168320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stbl 16841acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->endBox(); // minf 168520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // mdia 168620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // trak 168720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 168820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 168920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 1690