MPEG4Writer.cpp revision 1f90c4b3fda9dbd2824d67fd679f850572f114dc
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 3719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h" 3819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongstatic const int64_t kMax32BitFileSize = 0x007fffffffLL; 423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07; 433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08; 443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 4725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track(MPEG4Writer *owner, const sp<MediaSource> &source); 488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 5237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t stop(); 5337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 5425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 563b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 57d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 581acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong void writeTrackHeader(int32_t trackID, bool use32BitOffset = true); 591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addChunkOffset(off_t offset); 64dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 69693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 71a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 72a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 76c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 77e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 78e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // For realtime applications, we need to adjust the media clock 79e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // for video track based on the audio media clock 80e259531ce59ab1f31de5a23124b22536f6a5a767James Dong bool mIsRealTimeRecording; 81e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int64_t mMaxTimeStampUs; 82d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 88ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // mNumSamples is used to track how many samples in mSampleSizes List. 89ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // This is to reduce the cost associated with mSampleSizes.size() call, 90ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // since it is O(n). Ideally, the fix should be in List class. 91ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong size_t mNumSamples; 928644c14618d30d9e57a69df40ed939986ebf02c4James Dong List<size_t> mSampleSizes; 93be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong bool mSamplesHaveSameSize; 94be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 9513aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStcoTableEntries; 9813aec890216948b0c364f8f92792129d0335f506James Dong List<off_t> mChunkOffsets; 9913aec890216948b0c364f8f92792129d0335f506James Dong 1001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStscTableEntries; 10113aec890216948b0c364f8f92792129d0335f506James Dong struct StscTableEntry { 10213aec890216948b0c364f8f92792129d0335f506James Dong 10313aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 10413aec890216948b0c364f8f92792129d0335f506James Dong : firstChunk(chunk), 10513aec890216948b0c364f8f92792129d0335f506James Dong samplesPerChunk(samples), 10613aec890216948b0c364f8f92792129d0335f506James Dong sampleDescriptionId(id) {} 10713aec890216948b0c364f8f92792129d0335f506James Dong 10813aec890216948b0c364f8f92792129d0335f506James Dong uint32_t firstChunk; 10913aec890216948b0c364f8f92792129d0335f506James Dong uint32_t samplesPerChunk; 11013aec890216948b0c364f8f92792129d0335f506James Dong uint32_t sampleDescriptionId; 11113aec890216948b0c364f8f92792129d0335f506James Dong }; 11213aec890216948b0c364f8f92792129d0335f506James Dong List<StscTableEntry> mStscTableEntries; 11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStssTableEntries; 115050b28a593350047845a45a14cc5026221ac1620James Dong List<int32_t> mStssTableEntries; 116365a963142093a1cd8efdcea76b5f65096a5b115James Dong List<int64_t> mChunkDurations; 117050b28a593350047845a45a14cc5026221ac1620James Dong 1181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumSttsTableEntries; 119be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong struct SttsTableEntry { 120be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 1218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong SttsTableEntry(uint32_t count, uint32_t durationUs) 1228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong : sampleCount(count), sampleDurationUs(durationUs) {} 123be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 124be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t sampleCount; 1258f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong uint32_t sampleDurationUs; 126be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong }; 127be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SttsTableEntry> mSttsTableEntries; 128be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 1293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 1303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 1313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 1323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 1333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 1343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 1353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 1363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 1373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 1383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 1393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 1403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 1413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 1423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 145548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 14693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 1493c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 15093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 15193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 15225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 15437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 1573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 1583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t makeAVCCodecSpecificData( 16003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size); 1613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong status_t copyAVCCodecSpecificData( 1623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size); 1633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong status_t parseAVCCodecSpecificData( 1643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size); 165215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 166215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 167faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 16893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 16903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 170215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Utilities for collecting statistical data 171215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong void logStatisticalData(bool isAudio); 172215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong void findMinAvgMaxSampleDurationMs( 173215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t *min, int32_t *avg, int32_t *max); 174215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong void findMinMaxChunkDurations(int64_t *min, int64_t *max); 175215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 17619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 17719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 178c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 179c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 180c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 181c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 182c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 183c059860c73678a202bfa33062723e8f82fb779d9James Dong 184690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 185690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 186690f546b0ee548dbfe997df36418e5302ec2d786James Dong 1871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 1881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 1891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 1901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneSttsTableEntry(size_t sampleCount, int64_t durationUs); 1911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#define USE_NALLEN_FOUR 1 19703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFile(fopen(filename, "wb")), 2001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 201a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 202a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 20413aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 2057837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 206f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong mInterleaveDurationUs(1000000) { 2070c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mFile != NULL); 20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21030ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 21130ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mFile(fdopen(fd, "wb")), 2121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 213a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 214a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 21530ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 21613aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 2177837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 218f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong mInterleaveDurationUs(1000000) { 21930ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(mFile != NULL); 22030ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 22130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 22220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2251f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 2261f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 2281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 2291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 234dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 235dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 236dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 237dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 238dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 239dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 240dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 241dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 242dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 243dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 244dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 245dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 246dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 247dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 248dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 249dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 250dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 251dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 252dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) const { 253dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 254dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 255dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 256dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 257dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 258dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 259dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 260dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 261dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 262dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 263dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 264dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 2652dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 26625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track *track = new Track(this, source); 26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 2682dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 2692dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 273a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 274a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 27593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 276a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 277a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 278a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 279a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 280a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 281a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 282a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 283a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 284a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 285a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 286a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 287a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 288a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2892dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 2902dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 2912dec2b5be2056c6d9428897dc672185872d30d17James Dong // 2922dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 2932dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 2942dec2b5be2056c6d9428897dc672185872d30d17James Dong // Currently, lets set to 0.4% for now. 2952dec2b5be2056c6d9428897dc672185872d30d17James Dong 2962dec2b5be2056c6d9428897dc672185872d30d17James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB, 2972dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 2982dec2b5be2056c6d9428897dc672185872d30d17James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 4 2992dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 3002dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 3012dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 3022dec2b5be2056c6d9428897dc672185872d30d17James Dong 3032dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 3042dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 3052dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 3062dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024; // 4 KB 3072dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 3082dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 3092dec2b5be2056c6d9428897dc672185872d30d17James Dong 3102dec2b5be2056c6d9428897dc672185872d30d17James Dong if (mMaxFileSizeLimitBytes != 0) { 3112dec2b5be2056c6d9428897dc672185872d30d17James Dong size = mMaxFileSizeLimitBytes * 4 / 1000; 3122dec2b5be2056c6d9428897dc672185872d30d17James Dong } else if (mMaxFileDurationLimitUs != 0) { 3132dec2b5be2056c6d9428897dc672185872d30d17James Dong if (bitRate <= 0) { 3142dec2b5be2056c6d9428897dc672185872d30d17James Dong // We could not estimate the file size since bitRate is not set. 3152dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 3162dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 3172dec2b5be2056c6d9428897dc672185872d30d17James Dong size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000); 3182dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3192dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3202dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 3212dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 3222dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3232dec2b5be2056c6d9428897dc672185872d30d17James Dong 3242dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 3252dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 3262dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 3272dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 3282dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3292dec2b5be2056c6d9428897dc672185872d30d17James Dong 3302dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 3312dec2b5be2056c6d9428897dc672185872d30d17James Dong " moov size %lld bytes", 3322dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 3332dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 3342dec2b5be2056c6d9428897dc672185872d30d17James Dong} 3352dec2b5be2056c6d9428897dc672185872d30d17James Dong 3362dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 33825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 34020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3412dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 3422dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 3432dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 3442dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 3452dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 3462dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3472dec2b5be2056c6d9428897dc672185872d30d17James Dong 3481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 3491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 3501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 3511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 3521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 3531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 3541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 3551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 3561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 3571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong LOGE("32-bit file size limit too big: %lld bytes", 3581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes); 3591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return UNKNOWN_ERROR; 3601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 3611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 3621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 3632dec2b5be2056c6d9428897dc672185872d30d17James Dong // System property can overwrite the file offset bits parameter 3642dec2b5be2056c6d9428897dc672185872d30d17James Dong char value[PROPERTY_VALUE_MAX]; 3652dec2b5be2056c6d9428897dc672185872d30d17James Dong if (property_get("media.stagefright.record-64bits", value, NULL) 3662dec2b5be2056c6d9428897dc672185872d30d17James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 3672dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 3682dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3692dec2b5be2056c6d9428897dc672185872d30d17James Dong 370065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 37193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 372a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 373a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 374a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 37593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 376a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 377a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 378a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 379a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 3808f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 3818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 3828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 3838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 3848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 3858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("movie time scale: %d", mTimeScale); 3868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 3877837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = true; 3887837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 3897837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 3907837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 3917837c17063a4c50bc856ba59418516fdab731de7James Dong 39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("ftyp"); 39393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 39493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t fileType; 39593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (param && param->findInt32(kKeyFileType, &fileType) && 39693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong fileType != OUTPUT_FORMAT_MPEG_4) { 39793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("3gp4"); 39893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } else { 39993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("isom"); 40093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 40193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 40493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("3gp4"); 40520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); 40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4077837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4097837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 4102dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 4112dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 4122dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 4132dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4142dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 4157837c17063a4c50bc856ba59418516fdab731de7James Dong } 4167837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mEstimatedMoovBoxSize >= 8); 4177837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 4187837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize); 4197837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 4207837c17063a4c50bc856ba59418516fdab731de7James Dong 4217837c17063a4c50bc856ba59418516fdab731de7James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 4227837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 4237837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 4241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 4251acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 4261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 4271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 4281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 4291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 4311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 4321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 4331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 4341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 436a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 437a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 4391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 440a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 44125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 4451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 4461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 4471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 44837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 449a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mFile == NULL) { 45037187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 451a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 452a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 45337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 454a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 455a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 45637187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 45737187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 45837187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 45937187916a486504acaf83bea30147eb5fbf46ae5James Dong } 460a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 46137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 462a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 463a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 4641c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 4651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("stopWriterThread"); 4661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 4681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 4691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 4711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 4721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 4731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 4751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 4761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 4771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 47837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::stop() { 47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 48037187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 48120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 48220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 48337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 4848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 48520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 48620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 48737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 48837187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 48937187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 49037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 49120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 4938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 4948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 49520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 4997837c17063a4c50bc856ba59418516fdab731de7James Dong 50037187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 50137187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 50237187916a486504acaf83bea30147eb5fbf46ae5James Dong fflush(mFile); 50337187916a486504acaf83bea30147eb5fbf46ae5James Dong fclose(mFile); 50437187916a486504acaf83bea30147eb5fbf46ae5James Dong mFile = NULL; 50537187916a486504acaf83bea30147eb5fbf46ae5James Dong mStarted = false; 50637187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 50737187916a486504acaf83bea30147eb5fbf46ae5James Dong } 50837187916a486504acaf83bea30147eb5fbf46ae5James Dong 50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 5101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 5111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 5121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 5131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fwrite(&size, 1, 4, mFile); 5141acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 5151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fseeko(mFile, mMdatOffset + 8, SEEK_SET); 5161acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int64_t size = mOffset - mMdatOffset; 5171acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 5181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fwrite(&size, 1, 8, mFile); 5191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 5207837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 5237837c17063a4c50bc856ba59418516fdab731de7James Dong const off_t moovOffset = mOffset; 5247837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = true; 5257837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 5267837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 5277837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 528c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6; 52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("moov"); 53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("mvhd"); 53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // version=0, flags=0 53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // creation time 53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // modification time 5368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong writeInt32(mTimeScale); // mvhd timescale 5371acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(duration); 5381acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(0x10000); // rate: 1.0 53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0x100); // volume 54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0); // reserved 54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // matrix 54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 54620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); 54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x40000000); 55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mTracks.size() + 1); // nextTrackID 55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // mvhd 56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t id = 1; 56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it, ++id) { 5641acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong (*it)->writeTrackHeader(id, mUse32BitOffset); 56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // moov 56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5687837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 5697837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 5707837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 5717837c17063a4c50bc856ba59418516fdab731de7James Dong 5727837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 5737837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 5747837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 5757837c17063a4c50bc856ba59418516fdab731de7James Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); 5767837c17063a4c50bc856ba59418516fdab731de7James Dong 5777837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 5782dec2b5be2056c6d9428897dc672185872d30d17James Dong fseeko(mFile, mOffset, SEEK_SET); 5797837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 5807837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 5817837c17063a4c50bc856ba59418516fdab731de7James Dong 5827837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 5837837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 5847837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 5857837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 5862dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 5872dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("The mp4 file will not be streamable."); 5887837c17063a4c50bc856ba59418516fdab731de7James Dong } 5897837c17063a4c50bc856ba59418516fdab731de7James Dong 5900c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5927837c17063a4c50bc856ba59418516fdab731de7James Dong fflush(mFile); 59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fclose(mFile); 59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFile = NULL; 595a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = false; 59637187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59913aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 60013aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 60113aec890216948b0c364f8f92792129d0335f506James Dong return OK; 60213aec890216948b0c364f8f92792129d0335f506James Dong} 60313aec890216948b0c364f8f92792129d0335f506James Dong 60413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 60513aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 60613aec890216948b0c364f8f92792129d0335f506James Dong} 60713aec890216948b0c364f8f92792129d0335f506James Dong 60813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 60913aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 61013aec890216948b0c364f8f92792129d0335f506James Dong} 61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 61213aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t old_offset = mOffset; 61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1, buffer->range_length(), mFile); 61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 61820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 62403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 62503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 62603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 62703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 62803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 62903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 63003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 63103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 63203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 63303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 63403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 63503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 63603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 63713aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 63830ab66297501757d745b9ae10da61adcd891f497Andreas Huber off_t old_offset = mOffset; 63930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 64030ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 64103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 64203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 64303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t x = length >> 24; 64403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 64503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 16) & 0xff; 64603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 64703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = (length >> 8) & 0xff; 64803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 64903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber x = length & 0xff; 65003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber fwrite(&x, 1, 1, mFile); 65103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 65230ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(length < 65536); 65330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 65430ab66297501757d745b9ae10da61adcd891f497Andreas Huber uint8_t x = length >> 8; 65530ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 65630ab66297501757d745b9ae10da61adcd891f497Andreas Huber x = length & 0xff; 65730ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite(&x, 1, 1, mFile); 65803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 65930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 66030ab66297501757d745b9ae10da61adcd891f497Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 66130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1, length, mFile); 66230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 66303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 66403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mOffset += length + 4; 66503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 66630ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset += length + 2; 66703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 66830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 66930ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 67030ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 67130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 6727837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 6737837c17063a4c50bc856ba59418516fdab731de7James Dong const void *ptr, size_t size, size_t nmemb, FILE *stream) { 6747837c17063a4c50bc856ba59418516fdab731de7James Dong 6757837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 6767837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 6771acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 6781acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 6797837c17063a4c50bc856ba59418516fdab731de7James Dong for (List<off_t>::iterator it = mBoxes.begin(); 6807837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 6817837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 6827837c17063a4c50bc856ba59418516fdab731de7James Dong } 6837837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 6847837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); 6857837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 6867837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 6877837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 6887837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 6897837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 6907837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 6917837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = false; 6927837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 6937837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 6947837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 6957837c17063a4c50bc856ba59418516fdab731de7James Dong } 6967837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 6977837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 6987837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 6997837c17063a4c50bc856ba59418516fdab731de7James Dong } 7007837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 7017837c17063a4c50bc856ba59418516fdab731de7James Dong} 7027837c17063a4c50bc856ba59418516fdab731de7James Dong 70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 7040c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7067837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 7077837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 71320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 7140c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset = *--mBoxes.end(); 71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 71820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7197837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 7207837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 7217837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 7227837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 7237837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, offset, SEEK_SET); 7247837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 7257837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 7267837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 7277837c17063a4c50bc856ba59418516fdab731de7James Dong } 72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 7317837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 1, mFile); 73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 7367837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 2, mFile); 73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 7417837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 4, mFile); 74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 7467837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 8, mFile); 74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 7517837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, n + 1, mFile); 75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 7550c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 7567837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, 4, mFile); 75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 7607837c17063a4c50bc856ba59418516fdab731de7James Dong write(data, 1, size, mFile); 76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 763d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 764d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 765d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 766d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 767d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 768d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 769956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 770d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 771d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 772d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 773d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 7741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 7751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return (nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes); 776d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 777d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 778d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 779d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 780d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 781d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 782d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 783d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 784d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 785d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 786d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 787d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 788d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 789d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 790d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 791d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 792d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 79325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 79425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 79525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 79625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 79725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 79825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 79925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 80025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 80125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 80225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 80325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 80425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 80525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 806f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 807f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("setStartTimestampUs: %lld", timeUs); 808f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong CHECK(timeUs >= 0); 8093c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 810065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 811f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 812f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("Earliest track starting time: %lld", mStartTimestampUs); 8133c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 8143c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 8153c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 816f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 8173c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 8183c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 8193c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 8203c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 82158ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 82258ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 82358ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 82458ae9c530247668f8af36e30d228c716c226b3d4James Dong} 82558ae9c530247668f8af36e30d228c716c226b3d4James Dong 82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 82820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 82925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber MPEG4Writer *owner, const sp<MediaSource> &source) 83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 83125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 83220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 83320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 834a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 835a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 836c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 837956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 838be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 84025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 841548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 84225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS(false) { 84319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 8448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 8451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 8461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 8471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 8481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 8491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 8501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 8511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 852c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 853c059860c73678a202bfa33062723e8f82fb779d9James Dong} 854c059860c73678a202bfa33062723e8f82fb779d9James Dong 8551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 8561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset() 8581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ? mNumStcoTableEntries * 4 8591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong : mNumStcoTableEntries * 8; 8601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4); 8621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mEstimatedTrackSizeBytes = mMdatSizeBytes + // media data size 8641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStscTableEntries * 12 + // stsc box size 8651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStssTableEntries * 4 + // stss box size 8661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumSttsTableEntries * 8 + // stts box size 8671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong stcoBoxSizeBytes + // stco box size 8681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong stszBoxSizeBytes; // stsz box size 8691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 8721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 8731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong StscTableEntry stscEntry(chunkId, sampleId, 1); 8751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mStscTableEntries.push_back(stscEntry); 8761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStscTableEntries; 8771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 8801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mStssTableEntries.push_back(sampleId); 8811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStssTableEntries; 8821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 8851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t sampleCount, int64_t durationUs) { 8861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong SttsTableEntry sttsEntry(sampleCount, durationUs); 8881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mSttsTableEntries.push_back(sttsEntry); 8891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumSttsTableEntries; 8901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addChunkOffset(off_t offset) { 8931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStcoTableEntries; 8941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mChunkOffsets.push_back(offset); 8951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 897c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 898c059860c73678a202bfa33062723e8f82fb779d9James Dong LOGV("setTimeScale"); 899c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 900c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 901c059860c73678a202bfa33062723e8f82fb779d9James Dong 902c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 903c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 904c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 905c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 906c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 907c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 908c059860c73678a202bfa33062723e8f82fb779d9James Dong } 909c059860c73678a202bfa33062723e8f82fb779d9James Dong 910c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 911c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 912c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 913c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 914c059860c73678a202bfa33062723e8f82fb779d9James Dong } 915c059860c73678a202bfa33062723e8f82fb779d9James Dong 9168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 91719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 91819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 91919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 92019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 92119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 92219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 92319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 92419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 92519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 92619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 92719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 92819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 92919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 93019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 93119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 93219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 93319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 93419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 93519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 93619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 93719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 93819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 93919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 94019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 94119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 94219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 94319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 94419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 94519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 94619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 94719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 94820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 96093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("initTrackingProgressStatus"); 96193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 96293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 96393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 96493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 96593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 96693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 96793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Receive request to track progress status for every %lld us", timeUs); 96893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 96993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 97093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 97193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 97293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 97393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 9741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 9751c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 9761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("ThreadWrapper: %p", me); 9771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 9781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 9791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 9801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 9811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9821c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 9831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("bufferChunk: %p", chunk.mTrack); 9841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 9851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 9861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 9881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 9891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 9911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 9921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 9931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 9941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 9951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 9961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK("Received a chunk for a unknown track" == 0); 9981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 9991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10001c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeFirstChunk(ChunkInfo* info) { 10011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("writeFirstChunk: %p", info->mTrack); 10021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = info->mChunks.begin(); 10041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); 10051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != chunkIt->mSamples.end(); ++it) { 10061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong off_t offset = info->mTrack->isAvc() 10081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ? addLengthPrefixedSample_l(*it) 10091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong : addSample_l(*it); 10101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it == chunkIt->mSamples.begin()) { 10111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info->mTrack->addChunkOffset(offset); 10121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Done with the current chunk. 10161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Release all the samples in this chunk. 10171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!chunkIt->mSamples.empty()) { 10181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); 10191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 10201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 10211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong chunkIt->mSamples.erase(it); 10221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong chunkIt->mSamples.clear(); 10241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info->mChunks.erase(chunkIt); 10251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 10261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10271c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeChunks() { 10281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("writeChunks"); 10291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 10301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mChunkInfos.empty()) { 10311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<ChunkInfo>::iterator it = mChunkInfos.begin(); 10321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!it->mChunks.empty()) { 10331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(OK, writeOneChunk()); 10341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ++outstandingChunks; 10351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mTrack = NULL; 10371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.erase(it); 10381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 10401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGD("%d chunks are written in the last batch", outstandingChunks); 10411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 10421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10431c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::writeOneChunk() { 10441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("writeOneChunk"); 10451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Find the smallest timestamp, and write that chunk out 10471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // XXX: What if some track is just too slow? 10481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 10491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 10501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 10511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 10521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 10531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 10541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 10551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 10561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 10571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 10621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("Nothing to be written after all"); 10631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 10641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 10671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 10681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 10701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 10711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 10721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writeFirstChunk(&(*it)); 10731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 10761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 10771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10781c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 10791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("threadFunc"); 10801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 10821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 10831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 10841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 10851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(writeOneChunk(), OK); 10861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 10901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Write ALL samples 10911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 10921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writeChunks(); 10931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 10951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10961c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 10971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("startWriterThread"); 10981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 11001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1101e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 11021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 11031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 11041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 11051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 11061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 11071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 11081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 11101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 11111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 11121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 11131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 11141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 11151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 11161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 111893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1119a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1120a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1121a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1122a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1123a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 112425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 112593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 112619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 112719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 112819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 112919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 1130e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mIsRealTimeRecording = true; 1131e259531ce59ab1f31de5a23124b22536f6a5a767James Dong { 1132e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int32_t isNotRealTime; 1133e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) { 1134e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mIsRealTimeRecording = (isNotRealTime == 0); 1135e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1136e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1137e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 113893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 113993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1140f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1141f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1142f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 114325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 114425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 114525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 114625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 114720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 114820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 114920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 115020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 115120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1153c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 115425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1155956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 11561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStcoTableEntries = 0; 11571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStssTableEntries = 0; 11581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStscTableEntries = 0; 11591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumSttsTableEntries = 0; 11601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 116225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 116320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 116425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 116525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 116620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 116837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1169a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 117037187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1171a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1172a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 117337187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 117537187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = (status_t) dummy; 118437187916a486504acaf83bea30147eb5fbf46ae5James Dong 118537187916a486504acaf83bea30147eb5fbf46ae5James Dong { 118637187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = mSource->stop(); 118737187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK && status != ERROR_END_OF_STREAM) { 118837187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 118937187916a486504acaf83bea30147eb5fbf46ae5James Dong } 119037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 119137187916a486504acaf83bea30147eb5fbf46ae5James Dong 119237187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 119625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 119725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 119825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 120437187916a486504acaf83bea30147eb5fbf46ae5James Dong return (void *) err; 120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1207548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber#include <ctype.h> 1208548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huberstatic void hexdump(const void *_data, size_t size) { 1209548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber const uint8_t *data = (const uint8_t *)_data; 1210548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t offset = 0; 1211548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber while (offset < size) { 1212548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("0x%04x ", offset); 1213548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1214548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber size_t n = size - offset; 1215548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (n > 16) { 1216548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber n = 16; 1217548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1218548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1219548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < 16; ++i) { 1220548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (i == 8) { 1221548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 1222548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1223548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1224548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (offset + i < size) { 1225548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%02x ", data[offset + i]); 1226548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 1227548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 1228548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1229548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1230548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1231548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf(" "); 1232548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1233548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber for (size_t i = 0; i < n; ++i) { 1234548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber if (isprint(data[offset + i])) { 1235548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("%c", data[offset + i]); 1236548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } else { 1237548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("."); 1238548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1239548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1240548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1241548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber printf("\n"); 1242548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 1243548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber offset += 16; 1244548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber } 1245548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber} 1246548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 12473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 12483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("getNalUnitType: %d", byte); 12493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 12513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 12523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 12533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 12553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 12563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("findNextStartCode: %p %d", data, length); 12583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 12603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 12613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 12623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 12633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 12653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 12663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 12683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 12693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 12713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 12723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("parseParamSet"); 12743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 12753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 12763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 12783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 12793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 12803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Param set is malformed, since its length is 0"); 12813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 12823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 12853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 12863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 12873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Seq parameter set malformed"); 12883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 12893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 12913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 12923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 12933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 12943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 12953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 12963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 12973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 12983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Inconsistent profile/level found in seq parameter sets"); 12993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 13003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 13033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 13043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 13053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 13073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 13083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 13103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 13113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("copyAVCCodecSpecificData"); 13123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 13143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 13153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 13163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Codec specific data length too short: %d", size); 13173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 13213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 13223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 13233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 13243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 13253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 13273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 13283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("parseAVCCodecSpecificData"); 13303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 13313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 13323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 13333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 13343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 13353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 13363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 13373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 13383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 13393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 13403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 13413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 13423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 13433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 13443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 13453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("SPS must come before PPS"); 13463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 13493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 13503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 13523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 13533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 13543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("SPS must come before PPS"); 13553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 13583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 13593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 13613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 13623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Only SPS and PPS Nal units are expected"); 13633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 13673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 13713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 13723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 13733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 13743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 13773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 13783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 13793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 13803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Cound not find sequence parameter set"); 13813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 13853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 13863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 13913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 13923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 13933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 13943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Cound not find picture parameter set"); 13953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 13983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Too many pic parameter sets (%d) found", nPicParamSets); 13993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 14003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 14043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 14053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 14063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 14073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 14083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 14093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 14103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 14143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 1415548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 141603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 141703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 1418548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber // hexdump(data, size); 1419548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 142003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 1421548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Already have codec specific data"); 142203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 142303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 142403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 14263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Codec specific data length too short: %d", size); 142703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 142803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 142903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 14313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 14323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 143303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 143403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 143603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 143703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 143803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 14403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 144103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 144203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 14433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 14443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 14453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 14463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 144703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 144903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 145003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 3; // length size == 4 bytes 145103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 145203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber header[4] = 0xfc | 1; // length size == 2 bytes 145303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 145403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 14563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 14573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 14583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 14593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 14603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 14613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 14623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 14633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 14643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 14653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 14673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 14683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 14693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 14723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 14733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 14743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 14753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 14763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 14773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 14783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 14793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 14803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 14813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 14833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 14843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 14853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 148603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 148703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 148803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 148903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14908644c14618d30d9e57a69df40ed939986ebf02c4James Dongstatic bool collectStatisticalData() { 14918644c14618d30d9e57a69df40ed939986ebf02c4James Dong char value[PROPERTY_VALUE_MAX]; 14928644c14618d30d9e57a69df40ed939986ebf02c4James Dong if (property_get("media.stagefright.record-stats", value, NULL) 14938644c14618d30d9e57a69df40ed939986ebf02c4James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 14948644c14618d30d9e57a69df40ed939986ebf02c4James Dong return true; 14958644c14618d30d9e57a69df40ed939986ebf02c4James Dong } 14968644c14618d30d9e57a69df40ed939986ebf02c4James Dong return false; 14978644c14618d30d9e57a69df40ed939986ebf02c4James Dong} 14988644c14618d30d9e57a69df40ed939986ebf02c4James Dong 149937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 150030ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 150113aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 150213aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 150313aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 150413aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 15058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t lastTimestampUs = 0; // Previous sample time stamp in ms 15068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t lastDurationUs = 0; // Between the previous two samples in ms 1507c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t currDurationTicks = 0; // Timescale based ticks 1508c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t lastDurationTicks = 0; // Timescale based ticks 15098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 1510be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 1511a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 15121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t timestampUs; 1513e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1514d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 15158644c14618d30d9e57a69df40ed939986ebf02c4James Dong bool collectStats = collectStatisticalData(); 151620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1517ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mNumSamples = 0; 151893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 152093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 152413aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1528a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 1529a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 1530a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 1531a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 1532a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 1533a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 1534a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 1535a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1536a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 153730ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 153830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 153903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 154003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 154103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 1542548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 1543548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 15441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 154503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 154603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 154703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 154803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 1549be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 15501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 155103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 155203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 155303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 155403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 155503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 155603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 155730ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 155830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 155930ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 156030ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 156130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1562548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 156330ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 1564a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1565a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1566d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 1567d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 1568d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 1569d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 1570d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 1571d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 1572d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 1573d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 1574d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 1575d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 15761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 1577e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 15788644c14618d30d9e57a69df40ed939986ebf02c4James Dong size_t sampleSize; 15791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong sampleSize = mIsAvc 158003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#if USE_NALLEN_FOUR 1581d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong ? copy->range_length() + 4 158203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#else 1583d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong ? copy->range_length() + 2 158403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#endif 1585d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong : copy->range_length(); 1586050b28a593350047845a45a14cc5026221ac1620James Dong 1587d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 15881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 15891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 15901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1591d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 1592d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 1593d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1594d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1595d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 1596d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 1597d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1598d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1599d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1600050b28a593350047845a45a14cc5026221ac1620James Dong 1601d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 1602d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 1603d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1604d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 1605d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1606d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 16078644c14618d30d9e57a69df40ed939986ebf02c4James Dong if (mSampleSizes.empty()) { 1608f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 1609f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 16103c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 161148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 1612a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 1613c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong previousPausedDurationUs += (timestampUs - mTrackDurationUs - lastDurationUs); 1614a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 1615a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1616a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1617a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 1618e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (mIsRealTimeRecording && !mIsAudio) { 1619e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // The minor adjustment on the timestamp is heuristic/experimental 1620e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // We are adjusting the timestamp to reduce the fluctuation of the duration 1621e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // of neighboring samples. This in turn helps reduce the track header size, 1622e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // especially, the number of entries in the "stts" box. 1623e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (mNumSamples > 1) { 1624d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong int64_t currDriftTimeUs = mOwner->getDriftTimeUs(); 1625d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong int64_t durationUs = timestampUs + currDriftTimeUs - lastTimestampUs; 1626e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int64_t diffUs = (durationUs > lastDurationUs) 1627e259531ce59ab1f31de5a23124b22536f6a5a767James Dong ? durationUs - lastDurationUs 1628e259531ce59ab1f31de5a23124b22536f6a5a767James Dong : lastDurationUs - durationUs; 1629e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (diffUs <= 5000) { // XXX: Magic number 5ms 1630e259531ce59ab1f31de5a23124b22536f6a5a767James Dong timestampUs = lastTimestampUs + lastDurationUs; 1631e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } else { 1632d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong timestampUs += currDriftTimeUs; 1633e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1634e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1635e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1636e259531ce59ab1f31de5a23124b22536f6a5a767James Dong CHECK(timestampUs >= 0); 1637e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (mNumSamples > 1) { 1638e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (timestampUs <= lastTimestampUs) { 16394f86a980fee1880dca61b828599fa6d76755a485James Dong LOGW("Frame arrives too late!"); 16404f86a980fee1880dca61b828599fa6d76755a485James Dong // Don't drop the late frame, since dropping a frame may cause 16414f86a980fee1880dca61b828599fa6d76755a485James Dong // problems later during playback 16424f86a980fee1880dca61b828599fa6d76755a485James Dong 16434f86a980fee1880dca61b828599fa6d76755a485James Dong // The idea here is to avoid having two or more samples with the 16444f86a980fee1880dca61b828599fa6d76755a485James Dong // same timestamp in the output file. 16454f86a980fee1880dca61b828599fa6d76755a485James Dong if (mTimeScale >= 1000000LL) { 164640e9940fadf22daa64c1e766fa8a855c7b149c17James Dong timestampUs = lastTimestampUs + 1; 16474f86a980fee1880dca61b828599fa6d76755a485James Dong } else { 164840e9940fadf22daa64c1e766fa8a855c7b149c17James Dong timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale; 16494f86a980fee1880dca61b828599fa6d76755a485James Dong } 1650e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1651e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1652e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1653a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong LOGV("time stamp: %lld and previous paused duration %lld", 1654a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs, previousPausedDurationUs); 1655c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 1656c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 16573b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 16583b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 16598644c14618d30d9e57a69df40ed939986ebf02c4James Dong mSampleSizes.push_back(sampleSize); 1660ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong ++mNumSamples; 1661ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples > 2) { 1662c059860c73678a202bfa33062723e8f82fb779d9James Dong // We need to use the time scale based ticks, rather than the 1663c059860c73678a202bfa33062723e8f82fb779d9James Dong // timestamp itself to determine whether we have to use a new 1664c059860c73678a202bfa33062723e8f82fb779d9James Dong // stts entry, since we may have rounding errors. 1665c059860c73678a202bfa33062723e8f82fb779d9James Dong // The calculation is intended to reduce the accumulated 1666c059860c73678a202bfa33062723e8f82fb779d9James Dong // rounding errors. 1667c059860c73678a202bfa33062723e8f82fb779d9James Dong currDurationTicks = 1668c059860c73678a202bfa33062723e8f82fb779d9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 1669c059860c73678a202bfa33062723e8f82fb779d9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 1670c059860c73678a202bfa33062723e8f82fb779d9James Dong 1671c059860c73678a202bfa33062723e8f82fb779d9James Dong if (currDurationTicks != lastDurationTicks) { 16721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneSttsTableEntry(sampleCount, lastDurationUs); 1673be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 1674be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1675be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 1676be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1677be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1678be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 1679ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples >= 2 && previousSampleSize != sampleSize) { 1680be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 1681be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 16828644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 1683be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 16848644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 1685c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 16868644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 1687e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (mIsRealTimeRecording && mIsAudio) { 1688d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong int64_t driftTimeUs = 0; 1689d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong if (meta_data->findInt64(kKeyDriftTime, &driftTimeUs)) { 1690d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mOwner->setDriftTimeUs(driftTimeUs); 1691e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1692e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 169320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1694d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 16951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStssTableEntry(mNumSamples); 1696d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 1697d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 169893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 169993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 170093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 170193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 1702faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 170393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 170458ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mOwner->numTracks() == 1) { 17051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 170658ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 170758ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mChunkOffsets.empty()) { 17081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 170958ae9c530247668f8af36e30d228c716c226b3d4James Dong } 171058ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 171158ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 171258ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 171358ae9c530247668f8af36e30d228c716c226b3d4James Dong } 171413aec890216948b0c364f8f92792129d0335f506James Dong 171513aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 171613aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 17171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 17181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 171913aec890216948b0c364f8f92792129d0335f506James Dong } else { 172013aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 172113aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 172213aec890216948b0c364f8f92792129d0335f506James Dong } else { 172313aec890216948b0c364f8f92792129d0335f506James Dong if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 172413aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 17258644c14618d30d9e57a69df40ed939986ebf02c4James Dong if (collectStats) { 17268644c14618d30d9e57a69df40ed939986ebf02c4James Dong mChunkDurations.push_back(timestampUs - chunkTimestampUs); 17278644c14618d30d9e57a69df40ed939986ebf02c4James Dong } 172813aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 172913aec890216948b0c364f8f92792129d0335f506James Dong (--(mStscTableEntries.end()))->samplesPerChunk != 173013aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size()) { 17311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(nChunks, mChunkSamples.size()); 173213aec890216948b0c364f8f92792129d0335f506James Dong } 17331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 173413aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 173513aec890216948b0c364f8f92792129d0335f506James Dong } 173613aec890216948b0c364f8f92792129d0335f506James Dong } 173713aec890216948b0c364f8f92792129d0335f506James Dong } 173813aec890216948b0c364f8f92792129d0335f506James Dong 173920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 174025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 17418644c14618d30d9e57a69df40ed939986ebf02c4James Dong if (mSampleSizes.empty()) { 174237187916a486504acaf83bea30147eb5fbf46ae5James Dong err = ERROR_MALFORMED; 1743690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else if (OK != checkCodecSpecificData()) { 1744690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 1745f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 1746faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong mOwner->trackProgressStatus(this, -1, err); 1747be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 174813aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 174958ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mOwner->numTracks() == 1) { 17501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(1, mNumSamples); 175158ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 17521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 17531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 175413aec890216948b0c364f8f92792129d0335f506James Dong } 175513aec890216948b0c364f8f92792129d0335f506James Dong 1756be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 1757be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 1758be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 1759ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples == 1) { 17608f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 1761be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1762be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 1763be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 17641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneSttsTableEntry(sampleCount, lastDurationUs); 1765c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 176625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 17671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 17681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video"); 1769365a963142093a1cd8efdcea76b5f65096a5b115James Dong 17701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong logStatisticalData(mIsAudio); 177137187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 177237187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 177337187916a486504acaf83bea30147eb5fbf46ae5James Dong } 177437187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 1775365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1776365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1777faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 1778faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong LOGV("trackProgressStatus: %lld us", timeUs); 1779215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 1780215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 178193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Fire time tracking progress status at %lld us", timeUs); 1782faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err); 178393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 178493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 178593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 178693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1787faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 1788faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong const MPEG4Writer::Track* track, int64_t timeUs, status_t err) { 1789faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 1790faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong int32_t nTracks = mTracks.size(); 1791faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong CHECK(nTracks >= 1); 1792faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong CHECK(nTracks < 64); // Arbitrary number 1793faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1794faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong int32_t trackNum = 0; 1795faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong#if 0 1796faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // In the worst case, we can put the trackNum 1797faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // along with MEDIA_RECORDER_INFO_COMPLETION_STATUS 1798faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // to report the progress. 1799faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong for (List<Track *>::iterator it = mTracks.begin(); 1800faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong it != mTracks.end(); ++it, ++trackNum) { 1801faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (track == (*it)) { 1802faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong break; 1803faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 1804faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 1805faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong#endif 1806faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong CHECK(trackNum < nTracks); 1807faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum <<= 16; 1808faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1809faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 1810faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 1811faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 1812faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong notify(MEDIA_RECORDER_EVENT_ERROR, 1813faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum | MEDIA_RECORDER_ERROR_UNKNOWN, 1814faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 1815faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 1816faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 1817faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1818faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 1819faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 1820faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong notify(MEDIA_RECORDER_EVENT_INFO, 1821faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS, 1822faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 1823faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 1824faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 1825faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 1826faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong notify(MEDIA_RECORDER_EVENT_INFO, 1827faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS, 1828faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 1829faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 1830faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 1831faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1832215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dongvoid MPEG4Writer::Track::findMinAvgMaxSampleDurationMs( 1833215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t *min, int32_t *avg, int32_t *max) { 18348644c14618d30d9e57a69df40ed939986ebf02c4James Dong CHECK(!mSampleSizes.empty()); 1835c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int32_t avgSampleDurationMs = mTrackDurationUs / 1000 / mNumSamples; 1836215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t minSampleDurationMs = 0x7FFFFFFF; 1837215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t maxSampleDurationMs = 0; 1838365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1839365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != mSttsTableEntries.end(); ++it) { 18408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t sampleDurationMs = 18418f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000; 1842215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (sampleDurationMs > maxSampleDurationMs) { 1843215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong maxSampleDurationMs = sampleDurationMs; 1844215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong } else if (sampleDurationMs < minSampleDurationMs) { 1845215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong minSampleDurationMs = sampleDurationMs; 1846365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1847215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong LOGI("sample duration: %d ms", sampleDurationMs); 1848365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1849215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(minSampleDurationMs != 0); 1850215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(avgSampleDurationMs != 0); 1851215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong CHECK(maxSampleDurationMs != 0); 1852215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong *min = minSampleDurationMs; 1853215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong *avg = avgSampleDurationMs; 1854215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong *max = maxSampleDurationMs; 1855365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1856365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1857365a963142093a1cd8efdcea76b5f65096a5b115James Dong// Don't count the last duration 1858365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) { 1859365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t duration = mOwner->interleaveDuration(); 1860365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t minChunkDuration = duration; 1861365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t maxChunkDuration = duration; 1862365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (mChunkDurations.size() > 1) { 1863365a963142093a1cd8efdcea76b5f65096a5b115James Dong for (List<int64_t>::iterator it = mChunkDurations.begin(); 1864365a963142093a1cd8efdcea76b5f65096a5b115James Dong it != --mChunkDurations.end(); ++it) { 1865365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (minChunkDuration > (*it)) { 1866365a963142093a1cd8efdcea76b5f65096a5b115James Dong minChunkDuration = (*it); 1867365a963142093a1cd8efdcea76b5f65096a5b115James Dong } else if (maxChunkDuration < (*it)) { 1868365a963142093a1cd8efdcea76b5f65096a5b115James Dong maxChunkDuration = (*it); 1869365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1870365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1871365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1872365a963142093a1cd8efdcea76b5f65096a5b115James Dong *min = minChunkDuration; 1873365a963142093a1cd8efdcea76b5f65096a5b115James Dong *max = maxChunkDuration; 1874365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1875365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1876365a963142093a1cd8efdcea76b5f65096a5b115James Dongvoid MPEG4Writer::Track::logStatisticalData(bool isAudio) { 1877c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (mTrackDurationUs <= 0 || mSampleSizes.empty()) { 1878365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("nothing is recorded"); 1879365a963142093a1cd8efdcea76b5f65096a5b115James Dong return; 1880365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1881365a963142093a1cd8efdcea76b5f65096a5b115James Dong 18828644c14618d30d9e57a69df40ed939986ebf02c4James Dong bool collectStats = collectStatisticalData(); 1883365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1884365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (collectStats) { 1885215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong LOGI("%s track - duration %lld us, total %d frames", 1886c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong isAudio? "audio": "video", mTrackDurationUs, 1887ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mNumSamples); 1888215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong int32_t min, avg, max; 1889215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong findMinAvgMaxSampleDurationMs(&min, &avg, &max); 1890215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max); 1891215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (!isAudio) { 1892215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong float avgFps = 1000.0 / avg; 1893215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong float minFps = 1000.0 / max; 1894215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong float maxFps = 1000.0 / min; 1895365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f", 1896215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong minFps, avgFps, maxFps); 1897365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1898365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1899365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t totalBytes = 0; 19008644c14618d30d9e57a69df40ed939986ebf02c4James Dong for (List<size_t>::iterator it = mSampleSizes.begin(); 19018644c14618d30d9e57a69df40ed939986ebf02c4James Dong it != mSampleSizes.end(); ++it) { 19028644c14618d30d9e57a69df40ed939986ebf02c4James Dong totalBytes += (*it); 1903365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1904c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong float bitRate = (totalBytes * 8000000.0) / mTrackDurationUs; 1905365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("avg bit rate (bps): %.2f", bitRate); 1906365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1907365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t duration = mOwner->interleaveDuration(); 1908365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (duration != 0) { // If interleaving is enabled 1909365a963142093a1cd8efdcea76b5f65096a5b115James Dong int64_t minChunk, maxChunk; 1910365a963142093a1cd8efdcea76b5f65096a5b115James Dong findMinMaxChunkDurations(&minChunk, &maxChunk); 1911365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld", 1912365a963142093a1cd8efdcea76b5f65096a5b115James Dong minChunk, duration, maxChunk); 1913365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1914365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 191513aec890216948b0c364f8f92792129d0335f506James Dong} 191613aec890216948b0c364f8f92792129d0335f506James Dong 1917d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 1918d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong LOGV("setDriftTimeUs: %lld us", driftTimeUs); 1919e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 1920d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 1921e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 1922e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1923e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 1924e259531ce59ab1f31de5a23124b22536f6a5a767James Dong LOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 1925e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 1926e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 1927e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 1928e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 19291c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 19301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("bufferChunk"); 19311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 19331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 193413aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 193520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 193620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19373b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 1938c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 193920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 194020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1941d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 1942d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 1943d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1944d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1945690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 1946690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 1947690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 1948690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 1949690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 1950690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 1951690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 1952690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 1953690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Missing codec specific data 1954690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 1955690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 1956690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 1957690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 1958690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 1959690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Unexepected codec specific data found 1960690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 1961690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 1962690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 1963690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 1964690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 1965690f546b0ee548dbfe997df36418e5302ec2d786James Dong 19661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader( 19671acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t trackID, bool use32BitOffset) { 196820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 196920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findCString(kKeyMIMEType, &mime); 19700c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 197120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("%s track time scale: %d", 19731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 19748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 197520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 19768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 19778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 197820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 197920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("trak"); 198020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 198120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("tkhd"); 19821acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Flags = 7 to indicate that the track is enabled, and 19831acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // part of the presentation 19841acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0x07); // version=0, flags=7 198520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 198620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 198720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(trackID); 198820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 19898f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t tkhdDuration = 19908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 19918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 199220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 199320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 199420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // layer 199520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // alternate group 19961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 199720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 199820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 199920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); // matrix 200020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 200120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 200220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 200320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); 200420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 200520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 200620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 200720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x40000000); 200820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAudio) { 201020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 201120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 201220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 201320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 201420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 201520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 20160c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 201720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2018050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2019050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 202020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 202120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // tkhd 202220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2023f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2024f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (mStartTimestampUs != moovStartTimeUs) { 20253c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("edts"); 20263c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("elst"); 20271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0); // version=0, flags=0: 32-bit time 20281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(2); // never ends with an empty list 20298f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 20308f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // First elst entry: specify the starting time offset 20318f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t offsetUs = mStartTimestampUs - moovStartTimeUs; 20328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6; 20338f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(seg); // in mvhd timecale 20348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(-1); // starting time offset 20358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(1 << 16); // rate = 1.0 20368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 20378f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // Second elst entry: specify the track duration 20388f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 20398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(seg); // in mvhd timescale 20401acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0); 20411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); 20423c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 20433c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 20443c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 20453c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 204620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdia"); 204720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 204820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdhd"); 204920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 205020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 205120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 20528f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(mTimeScale); // media timescale 20538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 20548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(mdhdDuration); // use media timescale 20551acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Language follows the three letter standard ISO-639-2/T 20561acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // 'e', 'n', 'g' for "English", for instance. 20571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Each character is packed as the difference between its ASCII value and 0x60. 20581acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // For "English", these are 00101, 01110, 00111. 20591acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // XXX: Where is the padding bit located: 0x15C7? 20601acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt16(0); // language code 206120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 206220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 206320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 206420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("hdlr"); 206520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 2066050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // component type: should be mhlr 20671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 206820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 206920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 207020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 20711acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Removing "r" for the name string just makes the string 4 byte aligned 20721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 207320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 207420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 207520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("minf"); 20761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAudio) { 207720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("smhd"); 207820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 207920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // balance 208020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 208120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 208220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 208320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("vmhd"); 20841acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0x01); // version=0, flags=1 208520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // graphics mode 208620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // opcolor 208720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 208820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 208920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 209020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 2091050b28a593350047845a45a14cc5026221ac1620James Dong 2092050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dinf"); 2093050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dref"); 2094050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 20951acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1); // entry count (either url or urn) 20961acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // The table index here refers to the sample description index 20971acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // in the sample table entries. 2098050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("url "); 20991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2100050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // url 2101050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dref 2102050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dinf 2103050b28a593350047845a45a14cc5026221ac1620James Dong 210420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stbl"); 210520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 210620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsd"); 210720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 210820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); // entry count 21091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAudio) { 211025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber const char *fourcc = NULL; 211118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 211225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "samr"; 211318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 211425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "sawb"; 2115050b28a593350047845a45a14cc5026221ac1620James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2116050b28a593350047845a45a14cc5026221ac1620James Dong fourcc = "mp4a"; 211725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } else { 211825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 211925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber CHECK(!"should not be here, unknown mime type."); 212025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 212125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 212225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mOwner->beginBox(fourcc); // audio format 212320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 212420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 2125050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x1); // data ref index 212620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 212720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 2128050b28a593350047845a45a14cc5026221ac1620James Dong int32_t nChannels; 2129050b28a593350047845a45a14cc5026221ac1620James Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2130050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(nChannels); // channel count 213120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(16); // sample size 213220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 213320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 213420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 213520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t samplerate; 213620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 21370c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 213820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(samplerate << 16); 2139050b28a593350047845a45a14cc5026221ac1620James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2140050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("esds"); 214151dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong CHECK(mCodecSpecificData); 214251dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong CHECK(mCodecSpecificDataSize > 0); 2143050b28a593350047845a45a14cc5026221ac1620James Dong 2144050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 2145050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x03); // ES_DescrTag 2146050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2147050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x0000);// ES_ID 2148050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); 2149050b28a593350047845a45a14cc5026221ac1620James Dong 2150050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2151050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2152050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2153050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x15); // streamType AudioStream 2154050b28a593350047845a45a14cc5026221ac1620James Dong 2155050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x03); // XXX 2156050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2157050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // max bit rate 2158050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // avg bit rate 2159050b28a593350047845a45a14cc5026221ac1620James Dong 2160050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2161050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(mCodecSpecificDataSize); 2162050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2163050b28a593350047845a45a14cc5026221ac1620James Dong 2164050b28a593350047845a45a14cc5026221ac1620James Dong static const uint8_t kData2[] = { 2165050b28a593350047845a45a14cc5026221ac1620James Dong 0x06, // SLConfigDescriptorTag 2166050b28a593350047845a45a14cc5026221ac1620James Dong 0x01, 2167050b28a593350047845a45a14cc5026221ac1620James Dong 0x02 2168050b28a593350047845a45a14cc5026221ac1620James Dong }; 2169050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(kData2, sizeof(kData2)); 2170050b28a593350047845a45a14cc5026221ac1620James Dong 2171050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // esds 21725aff464f67322cd13dc8ed165806971cfff2e4d5James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 21735aff464f67322cd13dc8ed165806971cfff2e4d5James Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 21745aff464f67322cd13dc8ed165806971cfff2e4d5James Dong // 3gpp2 Spec AMRSampleEntry fields 21755aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->beginBox("damr"); 21765aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeCString(" "); // vendor: 4 bytes 21775aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt8(0); // decoder version 21785aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 21795aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt8(0); // mode change period 21805aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt8(1); // frames per sample 21815aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->endBox(); 2182050b28a593350047845a45a14cc5026221ac1620James Dong } 218320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 218420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 218518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 218620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mp4v"); 218718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 218820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("s263"); 218930ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 219030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avc1"); 219120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 219225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 21930c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!"should not be here, unknown mime type."); 219420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 219520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 219620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 219720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 21981acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt16(1); // data ref index 219920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 220020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 220120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 220220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 220320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 220420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 220520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 220620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 220720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 22080c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 220920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 221020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(width); 221120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(height); 221220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // horiz resolution 221320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // vert resolution 221420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 221520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(1); // frame count 221620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(" ", 32); 221720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x18); // depth 221820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(-1); // predefined 221920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22200c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(23 + mCodecSpecificDataSize < 128); 222120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 222218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2223a37923e9a57d489e7bed2129369219039fa5f12cJames Dong CHECK(mCodecSpecificData); 2224a37923e9a57d489e7bed2129369219039fa5f12cJames Dong CHECK(mCodecSpecificDataSize > 0); 222520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("esds"); 222620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 222720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 222820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 222920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x03); // ES_DescrTag 223020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(23 + mCodecSpecificDataSize); 223120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x0000); // ES_ID 223220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x1f); 223320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 223420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x04); // DecoderConfigDescrTag 223520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(15 + mCodecSpecificDataSize); 223620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 223720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x11); // streamType VisualStream 223820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 223920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData[] = { 224020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 0x77, 0x00, 224120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00, 224220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00 224320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 224420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData, sizeof(kData)); 2245050b28a593350047845a45a14cc5026221ac1620James Dong 224620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 224720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 224820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(mCodecSpecificDataSize); 224920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 225020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 225120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData2[] = { 225220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x06, // SLConfigDescriptorTag 225320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 225420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x02 225520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 225620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData2, sizeof(kData2)); 225720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 225820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // esds 225918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 226020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("d263"); 226120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 226220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // vendor 226320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // decoder version 226420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(10); // level: 10 226520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // profile: 0 226620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 226720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // d263 226830ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 226951dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong CHECK(mCodecSpecificData); 227051dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong CHECK(mCodecSpecificDataSize > 0); 227130ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avcC"); 227230ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 227330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // avcC 227420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 227530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 22761acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->beginBox("pasp"); 22771acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // This is useful if the pixel is not square 22781acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // hspacing 22791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // vspacing 22801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->endBox(); // pasp 228130ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // mp4v, s263 or avc1 228220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 228320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsd 228420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 228520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stts"); 228620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 22871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mOwner->writeInt32(mNumSttsTableEntries); 2288c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t prevTimestampUs = 0; 2289be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 2290be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSttsTableEntries.end(); ++it) { 2291be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleCount); 2292c059860c73678a202bfa33062723e8f82fb779d9James Dong 2293c059860c73678a202bfa33062723e8f82fb779d9James Dong // Make sure that we are calculating the sample duration the exactly 2294c059860c73678a202bfa33062723e8f82fb779d9James Dong // same way as we made decision on how to create stts entries. 2295c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs; 2296c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL - 2297c059860c73678a202bfa33062723e8f82fb779d9James Dong (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2298c059860c73678a202bfa33062723e8f82fb779d9James Dong prevTimestampUs += (it->sampleCount * it->sampleDurationUs); 2299c059860c73678a202bfa33062723e8f82fb779d9James Dong 23008f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(dur); 230120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 230220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stts 230320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!mIsAudio) { 2305050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("stss"); 2306050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 23071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mOwner->writeInt32(mNumStssTableEntries); // number of sync frames 2308050b28a593350047845a45a14cc5026221ac1620James Dong for (List<int32_t>::iterator it = mStssTableEntries.begin(); 2309050b28a593350047845a45a14cc5026221ac1620James Dong it != mStssTableEntries.end(); ++it) { 2310050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(*it); 2311050b28a593350047845a45a14cc5026221ac1620James Dong } 2312050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // stss 2313050b28a593350047845a45a14cc5026221ac1620James Dong } 2314050b28a593350047845a45a14cc5026221ac1620James Dong 231520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsz"); 231620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 2317be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 23188644c14618d30d9e57a69df40ed939986ebf02c4James Dong List<size_t>::iterator it = mSampleSizes.begin(); 23198644c14618d30d9e57a69df40ed939986ebf02c4James Dong mOwner->writeInt32(*it); // default sample size 2320be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2321be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(0); 2322be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2323ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mOwner->writeInt32(mNumSamples); 2324be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (!mSamplesHaveSameSize) { 23258644c14618d30d9e57a69df40ed939986ebf02c4James Dong for (List<size_t>::iterator it = mSampleSizes.begin(); 23268644c14618d30d9e57a69df40ed939986ebf02c4James Dong it != mSampleSizes.end(); ++it) { 23278644c14618d30d9e57a69df40ed939986ebf02c4James Dong mOwner->writeInt32(*it); 2328be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 232920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 233020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsz 233120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 233220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsc"); 233320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 23341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mOwner->writeInt32(mNumStscTableEntries); 233513aec890216948b0c364f8f92792129d0335f506James Dong for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 233613aec890216948b0c364f8f92792129d0335f506James Dong it != mStscTableEntries.end(); ++it) { 233713aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->firstChunk); 233813aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->samplesPerChunk); 233913aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->sampleDescriptionId); 234020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 234120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsc 23421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 234320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 23441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mOwner->writeInt32(mNumStcoTableEntries); 234513aec890216948b0c364f8f92792129d0335f506James Dong for (List<off_t>::iterator it = mChunkOffsets.begin(); 234613aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkOffsets.end(); ++it) { 23471acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (use32BitOffset) { 23481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(static_cast<int32_t>(*it)); 23491acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 23501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt64((*it)); 23511acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 235220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 23538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->endBox(); // stco or co64 235420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 235520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stbl 23561acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->endBox(); // minf 235720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // mdia 235820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // trak 235920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 236020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 236120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 2362