MPEG4Writer.cpp revision 5f995b0e72ed6f186cb0ab2a525c4cfce614f3a9
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 <pthread.h> 24a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/prctl.h> 25a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong#include <sys/resource.h> 2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 300c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h> 3118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 3203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h> 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 35d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.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; 44872a481558350634a3fd5cb67939de288af00ecbJames Dongstatic const int64_t kVideoMediaTimeAdjustPeriodTimeUs = 10000000LL; // 10s 453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 4825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track(MPEG4Writer *owner, const sp<MediaSource> &source); 498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 5337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t stop(); 5437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 5525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 573b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 58d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 591acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong void writeTrackHeader(int32_t trackID, bool use32BitOffset = true); 601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addChunkOffset(off_t offset); 65dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 70693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 72a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 73a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 77c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 78e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 79e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // For realtime applications, we need to adjust the media clock 80e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // for video track based on the audio media clock 81e259531ce59ab1f31de5a23124b22536f6a5a767James Dong bool mIsRealTimeRecording; 82e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int64_t mMaxTimeStampUs; 83d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 89ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // mNumSamples is used to track how many samples in mSampleSizes List. 90ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // This is to reduce the cost associated with mSampleSizes.size() call, 91ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // since it is O(n). Ideally, the fix should be in List class. 92ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong size_t mNumSamples; 938644c14618d30d9e57a69df40ed939986ebf02c4James Dong List<size_t> mSampleSizes; 94be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong bool mSamplesHaveSameSize; 95be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 9613aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStcoTableEntries; 9913aec890216948b0c364f8f92792129d0335f506James Dong List<off_t> mChunkOffsets; 10013aec890216948b0c364f8f92792129d0335f506James Dong 1011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStscTableEntries; 10213aec890216948b0c364f8f92792129d0335f506James Dong struct StscTableEntry { 10313aec890216948b0c364f8f92792129d0335f506James Dong 10413aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 10513aec890216948b0c364f8f92792129d0335f506James Dong : firstChunk(chunk), 10613aec890216948b0c364f8f92792129d0335f506James Dong samplesPerChunk(samples), 10713aec890216948b0c364f8f92792129d0335f506James Dong sampleDescriptionId(id) {} 10813aec890216948b0c364f8f92792129d0335f506James Dong 10913aec890216948b0c364f8f92792129d0335f506James Dong uint32_t firstChunk; 11013aec890216948b0c364f8f92792129d0335f506James Dong uint32_t samplesPerChunk; 11113aec890216948b0c364f8f92792129d0335f506James Dong uint32_t sampleDescriptionId; 11213aec890216948b0c364f8f92792129d0335f506James Dong }; 11313aec890216948b0c364f8f92792129d0335f506James Dong List<StscTableEntry> mStscTableEntries; 11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStssTableEntries; 116050b28a593350047845a45a14cc5026221ac1620James Dong List<int32_t> mStssTableEntries; 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 153872a481558350634a3fd5cb67939de288af00ecbJames Dong // Has the media time adjustment for video started? 154872a481558350634a3fd5cb67939de288af00ecbJames Dong bool mIsMediaTimeAdjustmentOn; 155872a481558350634a3fd5cb67939de288af00ecbJames Dong // The time stamp when previous media time adjustment period starts 156872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t mPrevMediaTimeAdjustTimestampUs; 157872a481558350634a3fd5cb67939de288af00ecbJames Dong // Number of vidoe frames whose time stamp may be adjusted 158872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t mMediaTimeAdjustNumFrames; 159872a481558350634a3fd5cb67939de288af00ecbJames Dong // The sample number when previous meida time adjustmnet period starts 160872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t mPrevMediaTimeAdjustSample; 161872a481558350634a3fd5cb67939de288af00ecbJames Dong // The total accumulated drift time within a period of 162872a481558350634a3fd5cb67939de288af00ecbJames Dong // kVideoMediaTimeAdjustPeriodTimeUs. 163872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t mTotalDriftTimeToAdjustUs; 164872a481558350634a3fd5cb67939de288af00ecbJames Dong // The total accumalated drift time since the start of the recording 165872a481558350634a3fd5cb67939de288af00ecbJames Dong // excluding the current time adjustment period 166872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t mPrevTotalAccumDriftTimeUs; 167872a481558350634a3fd5cb67939de288af00ecbJames Dong 168872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 169872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 170872a481558350634a3fd5cb67939de288af00ecbJames Dong 171872a481558350634a3fd5cb67939de288af00ecbJames Dong // Adjust the time stamp of the video track according to 172872a481558350634a3fd5cb67939de288af00ecbJames Dong // the drift time information from the audio track. 173872a481558350634a3fd5cb67939de288af00ecbJames Dong void adjustMediaTime(int64_t *timestampUs); 174872a481558350634a3fd5cb67939de288af00ecbJames Dong 17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 17637187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 1793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 1803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 18103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t makeAVCCodecSpecificData( 18203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size); 1833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong status_t copyAVCCodecSpecificData( 1843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size); 1853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong status_t parseAVCCodecSpecificData( 1863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size); 187215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 188215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 189faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 19093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 19103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 19219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 19319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 194c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 195c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 196c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 197c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 198c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 199c059860c73678a202bfa33062723e8f82fb779d9James Dong 200690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 201690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 202690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 2041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 2051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 2061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneSttsTableEntry(size_t sampleCount, int64_t durationUs); 2071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFile(fopen(filename, "wb")), 214b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 2151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 216a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 217a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 218a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 22013aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 2217837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 222f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong mInterleaveDurationUs(1000000) { 2230c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mFile != NULL); 22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22630ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 22730ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mFile(fdopen(fd, "wb")), 228b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 2291acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 230a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 231a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 232a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 23330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 23413aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 2357837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 236f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong mInterleaveDurationUs(1000000) { 23730ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(mFile != NULL); 23830ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 23930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 24020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 2441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 2461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 2471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 252dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 253dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 254dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 255dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 256dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 257dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 258dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 259dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 260dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 261dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 262dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 263dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 264dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 265dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 266dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 267dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 268dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 269dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 270dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) const { 271dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 272dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 273dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 274dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 275dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 276dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 277dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 278dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 279dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 280dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 281dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 282dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 2832dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 28425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track *track = new Track(this, source); 28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 2862dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 2872dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 291a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 292a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 29393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 294a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 295a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 296a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 297a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 298a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 299a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 300a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 301a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 302a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 303a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 304a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 305a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 306a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 3072dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 3082dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 3092dec2b5be2056c6d9428897dc672185872d30d17James Dong // 3102dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 3112dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 3122dec2b5be2056c6d9428897dc672185872d30d17James Dong // Currently, lets set to 0.4% for now. 3132dec2b5be2056c6d9428897dc672185872d30d17James Dong 3142dec2b5be2056c6d9428897dc672185872d30d17James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB, 3152dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 3162dec2b5be2056c6d9428897dc672185872d30d17James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 4 3172dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 3182dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 3192dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 3202dec2b5be2056c6d9428897dc672185872d30d17James Dong 3212dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 3222dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 3232dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 3242dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024; // 4 KB 3252dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 3262dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 3272dec2b5be2056c6d9428897dc672185872d30d17James Dong 328a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 3292dec2b5be2056c6d9428897dc672185872d30d17James Dong size = mMaxFileSizeLimitBytes * 4 / 1000; 3302dec2b5be2056c6d9428897dc672185872d30d17James Dong } else if (mMaxFileDurationLimitUs != 0) { 3312dec2b5be2056c6d9428897dc672185872d30d17James Dong if (bitRate <= 0) { 3322dec2b5be2056c6d9428897dc672185872d30d17James Dong // We could not estimate the file size since bitRate is not set. 3332dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 3342dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 3352dec2b5be2056c6d9428897dc672185872d30d17James Dong size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000); 3362dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3372dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3382dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 3392dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 3402dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3412dec2b5be2056c6d9428897dc672185872d30d17James Dong 3422dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 3432dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 3442dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 3452dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 3462dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3472dec2b5be2056c6d9428897dc672185872d30d17James Dong 348a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 3492dec2b5be2056c6d9428897dc672185872d30d17James Dong " moov size %lld bytes", 3502dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 3512dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 3522dec2b5be2056c6d9428897dc672185872d30d17James Dong} 3532dec2b5be2056c6d9428897dc672185872d30d17James Dong 3542dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 35625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 359a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 360a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 361a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 362a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 363a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 364a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 365a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 366a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 367a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 368a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 3692dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 3702dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 3712dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 3722dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 3732dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 3742dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3752dec2b5be2056c6d9428897dc672185872d30d17James Dong 3761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 3771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 3781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 3791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 3801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 3811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 3821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 3831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 3841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 385872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGW("32-bit file size limit (%lld bytes) too big. " 386d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong "It is changed to %lld bytes", 387d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 388d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 3891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 3901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 3911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 392b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 393b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 394b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 395b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 396b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 3972dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3982dec2b5be2056c6d9428897dc672185872d30d17James Dong 399065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 40093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 401a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 402a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 403a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 40493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 405a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 406a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 407a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 408a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 4098f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 4108f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 4118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 4128f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 4138f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 4148f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("movie time scale: %d", mTimeScale); 4158f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 4167837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = true; 4177837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 4187837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 4197837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 4207837c17063a4c50bc856ba59418516fdab731de7James Dong 42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("ftyp"); 42293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 42393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t fileType; 42493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (param && param->findInt32(kKeyFileType, &fileType) && 42593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong fileType != OUTPUT_FORMAT_MPEG_4) { 42693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("3gp4"); 42793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } else { 42893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("isom"); 42993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 43093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 43393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("3gp4"); 43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); 43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4367837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4387837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 4392dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 4402dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 4412dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 4422dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4432dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 4447837c17063a4c50bc856ba59418516fdab731de7James Dong } 4457837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mEstimatedMoovBoxSize >= 8); 4467837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 4477837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize); 4487837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 4497837c17063a4c50bc856ba59418516fdab731de7James Dong 4507837c17063a4c50bc856ba59418516fdab731de7James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 4517837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 4527837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 4531acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 4541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 4551acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 4561acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 4571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 4581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 4601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 4611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 4621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 4631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 465a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 466a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 46720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 4681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 469a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 47025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 47120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 4741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 4751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 4761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 47737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 478a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mFile == NULL) { 47937187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 480a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 481a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 48237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 483a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 484a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 48537187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 48637187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 48737187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 48837187916a486504acaf83bea30147eb5fbf46ae5James Dong } 489a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 49037187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 491a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 492a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 4931c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 4941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("stopWriterThread"); 4951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 4971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 4981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 5001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 5011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 5021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 5031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 5041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 5051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 5061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 50737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::stop() { 50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 50937187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 51120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 51237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 5138f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 51637187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 51737187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 51837187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 51937187916a486504acaf83bea30147eb5fbf46ae5James Dong } 52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 5228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 5238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 5287837c17063a4c50bc856ba59418516fdab731de7James Dong 52937187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 53037187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 53137187916a486504acaf83bea30147eb5fbf46ae5James Dong fflush(mFile); 53237187916a486504acaf83bea30147eb5fbf46ae5James Dong fclose(mFile); 53337187916a486504acaf83bea30147eb5fbf46ae5James Dong mFile = NULL; 53437187916a486504acaf83bea30147eb5fbf46ae5James Dong mStarted = false; 53537187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 53637187916a486504acaf83bea30147eb5fbf46ae5James Dong } 53737187916a486504acaf83bea30147eb5fbf46ae5James Dong 53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 5391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 5401acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 5411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 5421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fwrite(&size, 1, 4, mFile); 5431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 5441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fseeko(mFile, mMdatOffset + 8, SEEK_SET); 5451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int64_t size = mOffset - mMdatOffset; 5461acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 5471acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fwrite(&size, 1, 8, mFile); 5481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 5497837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 5527837c17063a4c50bc856ba59418516fdab731de7James Dong const off_t moovOffset = mOffset; 5537837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = true; 5547837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 5557837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 5567837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 557c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6; 55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("moov"); 56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("mvhd"); 56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // version=0, flags=0 56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // creation time 56420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // modification time 5658f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong writeInt32(mTimeScale); // mvhd timescale 5661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(duration); 5671acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(0x10000); // rate: 1.0 56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0x100); // volume 56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0); // reserved 57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // matrix 57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); 57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x40000000); 58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mTracks.size() + 1); // nextTrackID 58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // mvhd 58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t id = 1; 59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it, ++id) { 5931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong (*it)->writeTrackHeader(id, mUse32BitOffset); 59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // moov 59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5977837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 5987837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 5997837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 6007837c17063a4c50bc856ba59418516fdab731de7James Dong 6017837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 6027837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 6037837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 6047837c17063a4c50bc856ba59418516fdab731de7James Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); 6057837c17063a4c50bc856ba59418516fdab731de7James Dong 6067837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 6072dec2b5be2056c6d9428897dc672185872d30d17James Dong fseeko(mFile, mOffset, SEEK_SET); 6087837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 6097837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 6107837c17063a4c50bc856ba59418516fdab731de7James Dong 6117837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 6127837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 6137837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 6147837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 6152dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 6162dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("The mp4 file will not be streamable."); 6177837c17063a4c50bc856ba59418516fdab731de7James Dong } 6187837c17063a4c50bc856ba59418516fdab731de7James Dong 6190c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6217837c17063a4c50bc856ba59418516fdab731de7James Dong fflush(mFile); 62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fclose(mFile); 62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFile = NULL; 624a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = false; 62537187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62813aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 62913aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 63013aec890216948b0c364f8f92792129d0335f506James Dong return OK; 63113aec890216948b0c364f8f92792129d0335f506James Dong} 63213aec890216948b0c364f8f92792129d0335f506James Dong 63313aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 63413aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 63513aec890216948b0c364f8f92792129d0335f506James Dong} 63613aec890216948b0c364f8f92792129d0335f506James Dong 63713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 63813aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 63913aec890216948b0c364f8f92792129d0335f506James Dong} 64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 64113aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t old_offset = mOffset; 64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1, buffer->range_length(), mFile); 64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 65203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 65303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 65403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 65503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 65603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 65703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 65803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 65903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 66003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 66103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 66203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 66303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 66403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 66503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 66613aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 66730ab66297501757d745b9ae10da61adcd891f497Andreas Huber off_t old_offset = mOffset; 66830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 66930ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 67003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 671b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 672b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 673b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite(&x, 1, 1, mFile); 674b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 675b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite(&x, 1, 1, mFile); 676b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 677b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite(&x, 1, 1, mFile); 678b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 679b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite(&x, 1, 1, mFile); 680b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 681b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 682b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1, length, mFile); 683b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 684b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 685b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong CHECK(length < 65536); 68630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 687b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 688b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite(&x, 1, 1, mFile); 689b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 690b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite(&x, 1, 1, mFile); 691b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 692b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1, length, mFile); 693b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 694b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 69530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 69630ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 69730ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 69830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 6997837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 7007837c17063a4c50bc856ba59418516fdab731de7James Dong const void *ptr, size_t size, size_t nmemb, FILE *stream) { 7017837c17063a4c50bc856ba59418516fdab731de7James Dong 7027837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 7037837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 7041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 7051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 7067837c17063a4c50bc856ba59418516fdab731de7James Dong for (List<off_t>::iterator it = mBoxes.begin(); 7077837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 7087837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 7097837c17063a4c50bc856ba59418516fdab731de7James Dong } 7107837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 7117837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); 7127837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 7137837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 7147837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 7157837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 7167837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 7177837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 7187837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = false; 7197837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 7207837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 7217837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 7227837c17063a4c50bc856ba59418516fdab731de7James Dong } 7237837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 7247837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 7257837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 7267837c17063a4c50bc856ba59418516fdab731de7James Dong } 7277837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 7287837c17063a4c50bc856ba59418516fdab731de7James Dong} 7297837c17063a4c50bc856ba59418516fdab731de7James Dong 73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 7310c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7337837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 7347837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 7410c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset = *--mBoxes.end(); 74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7467837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 7477837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 7487837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 7497837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 7507837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, offset, SEEK_SET); 7517837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 7527837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 7537837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 7547837c17063a4c50bc856ba59418516fdab731de7James Dong } 75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 7587837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 1, mFile); 75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 7637837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 2, mFile); 76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 7687837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 4, mFile); 76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 7737837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 8, mFile); 77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 7787837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, n + 1, mFile); 77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 7820c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 7837837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, 4, mFile); 78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 7877837c17063a4c50bc856ba59418516fdab731de7James Dong write(data, 1, size, mFile); 78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 78920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 790d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 791d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 792d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 793d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 794d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 795d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 796956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 797d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 798d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 799d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 800d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 8011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return (nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes); 803d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 804d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 805d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 806d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 807d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 808d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 809d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 810d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 811d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 812d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 813d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 814d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 815d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 816d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 817d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 818d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 819d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 82025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 82125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 82225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 82325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 82425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 82525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 82625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 82725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 82825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 82925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 83025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 83125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 83225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 833f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 834f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("setStartTimestampUs: %lld", timeUs); 835f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong CHECK(timeUs >= 0); 8363c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 837065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 838f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 839f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("Earliest track starting time: %lld", mStartTimestampUs); 8403c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 8413c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 8423c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 843f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 8443c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 8453c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 8463c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 8473c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 84858ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 84958ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 85058ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 85158ae9c530247668f8af36e30d228c716c226b3d4James Dong} 85258ae9c530247668f8af36e30d228c716c226b3d4James Dong 85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 85520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 85625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber MPEG4Writer *owner, const sp<MediaSource> &source) 85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 85825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 861a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 862a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 863c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 864956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 865be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 86725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 868548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 86925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS(false) { 87019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 8718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 8721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 8731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 8741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 8751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 8761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 8771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 8781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 879c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 880c059860c73678a202bfa33062723e8f82fb779d9James Dong} 881c059860c73678a202bfa33062723e8f82fb779d9James Dong 8821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 8831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset() 8851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ? mNumStcoTableEntries * 4 8861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong : mNumStcoTableEntries * 8; 8871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4); 8891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mEstimatedTrackSizeBytes = mMdatSizeBytes + // media data size 8911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStscTableEntries * 12 + // stsc box size 8921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStssTableEntries * 4 + // stss box size 8931f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumSttsTableEntries * 8 + // stts box size 8941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong stcoBoxSizeBytes + // stco box size 8951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong stszBoxSizeBytes; // stsz box size 8961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 8991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 9001f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 9011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong StscTableEntry stscEntry(chunkId, sampleId, 1); 9021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mStscTableEntries.push_back(stscEntry); 9031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStscTableEntries; 9041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 9051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 9061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 9071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mStssTableEntries.push_back(sampleId); 9081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStssTableEntries; 9091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 9101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 9111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 9121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t sampleCount, int64_t durationUs) { 9131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 9141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong SttsTableEntry sttsEntry(sampleCount, durationUs); 9151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mSttsTableEntries.push_back(sttsEntry); 9161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumSttsTableEntries; 9171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 9181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 9191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addChunkOffset(off_t offset) { 9201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStcoTableEntries; 9211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mChunkOffsets.push_back(offset); 9221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 9231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 924c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 925c059860c73678a202bfa33062723e8f82fb779d9James Dong LOGV("setTimeScale"); 926c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 927c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 928c059860c73678a202bfa33062723e8f82fb779d9James Dong 929c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 930c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 931c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 932c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 933c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 934c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 935c059860c73678a202bfa33062723e8f82fb779d9James Dong } 936c059860c73678a202bfa33062723e8f82fb779d9James Dong 937c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 938c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 939c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 940c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 941c059860c73678a202bfa33062723e8f82fb779d9James Dong } 942c059860c73678a202bfa33062723e8f82fb779d9James Dong 9438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 94419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 94519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 94619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 94719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 94819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 94919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 95019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 95119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 95219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 95319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 95419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 95519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 95619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 95719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 95819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 95919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 96019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 96119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 96219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 96319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 96419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 96519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 96619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 96719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 96819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 96919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 97019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 97119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 97219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 97319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 97419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 97720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 98693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 98793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("initTrackingProgressStatus"); 98893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 98993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 99093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 99193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 99293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 99393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 99493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Receive request to track progress status for every %lld us", timeUs); 99593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 99693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 99793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 99893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 99993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 100093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 10011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 10021c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 10031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("ThreadWrapper: %p", me); 10041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 10051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 10061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 10071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 10081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10091c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 10101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("bufferChunk: %p", chunk.mTrack); 10111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 10121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 10131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 10151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 10161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 10181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 10191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 10201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 10211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK("Received a chunk for a unknown track" == 0); 10251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 10261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10271c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeFirstChunk(ChunkInfo* info) { 10281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("writeFirstChunk: %p", info->mTrack); 10291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = info->mChunks.begin(); 10311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); 10321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != chunkIt->mSamples.end(); ++it) { 10331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong off_t offset = info->mTrack->isAvc() 10351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ? addLengthPrefixedSample_l(*it) 10361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong : addSample_l(*it); 10371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it == chunkIt->mSamples.begin()) { 10381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info->mTrack->addChunkOffset(offset); 10391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Done with the current chunk. 10431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Release all the samples in this chunk. 10441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!chunkIt->mSamples.empty()) { 10451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); 10461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 10471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 10481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong chunkIt->mSamples.erase(it); 10491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong chunkIt->mSamples.clear(); 10511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info->mChunks.erase(chunkIt); 10521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 10531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10541c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeChunks() { 10551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("writeChunks"); 10561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 10571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mChunkInfos.empty()) { 10581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<ChunkInfo>::iterator it = mChunkInfos.begin(); 10591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!it->mChunks.empty()) { 10601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(OK, writeOneChunk()); 10611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ++outstandingChunks; 10621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mTrack = NULL; 10641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.erase(it); 10651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 10671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGD("%d chunks are written in the last batch", outstandingChunks); 10681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 10691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10701c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::writeOneChunk() { 10711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("writeOneChunk"); 10721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Find the smallest timestamp, and write that chunk out 10741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // XXX: What if some track is just too slow? 10751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 10761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 10771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 10781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 10791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 10801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 10811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 10821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 10831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 10841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 10891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("Nothing to be written after all"); 10901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 10911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 10941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 10951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 10971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 10981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 10991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writeFirstChunk(&(*it)); 11001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 11011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 11021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 11031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 11041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11051c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 11061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("threadFunc"); 11071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1108a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 11091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 11101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 11111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 11121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 11131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(writeOneChunk(), OK); 11141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 11151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 11161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 11181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Write ALL samples 11191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 11201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writeChunks(); 11211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 11221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 11231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11241c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 11251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("startWriterThread"); 11261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 11281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1129e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 11301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 11311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 11321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 11331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 11341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 11351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 11361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 11381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 11391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 11401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 11411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 11421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 11431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 11441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 114693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1147a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1148a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1149a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1150a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1151a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 115225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 115393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 115419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 115519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 115619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 115719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 1158d0ea545d8357e7d86ad5f19cb2c6499c91786473James Dong mIsRealTimeRecording = false; 1159e259531ce59ab1f31de5a23124b22536f6a5a767James Dong { 1160e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int32_t isNotRealTime; 1161e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) { 1162e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mIsRealTimeRecording = (isNotRealTime == 0); 1163e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1164e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1165e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 116693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 116793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1168f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1169f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1170f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 117125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 117225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 117325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 117425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1181c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 118225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1183956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 11841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStcoTableEntries = 0; 11851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStssTableEntries = 0; 11861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStscTableEntries = 0; 11871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumSttsTableEntries = 0; 11881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 1189872a481558350634a3fd5cb67939de288af00ecbJames Dong mIsMediaTimeAdjustmentOn = false; 1190872a481558350634a3fd5cb67939de288af00ecbJames Dong mPrevMediaTimeAdjustTimestampUs = 0; 1191872a481558350634a3fd5cb67939de288af00ecbJames Dong mMediaTimeAdjustNumFrames = 0; 1192872a481558350634a3fd5cb67939de288af00ecbJames Dong mPrevMediaTimeAdjustSample = 0; 1193872a481558350634a3fd5cb67939de288af00ecbJames Dong mTotalDriftTimeToAdjustUs = 0; 1194872a481558350634a3fd5cb67939de288af00ecbJames Dong mPrevTotalAccumDriftTimeUs = 0; 119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 119825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 119925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1203a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 120437187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1205a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1206a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 120737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 120937187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 121020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = (status_t) dummy; 121837187916a486504acaf83bea30147eb5fbf46ae5James Dong 121937187916a486504acaf83bea30147eb5fbf46ae5James Dong { 122037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = mSource->stop(); 122137187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK && status != ERROR_END_OF_STREAM) { 122237187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 122337187916a486504acaf83bea30147eb5fbf46ae5James Dong } 122437187916a486504acaf83bea30147eb5fbf46ae5James Dong } 122537187916a486504acaf83bea30147eb5fbf46ae5James Dong 122637187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 122925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 123025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 123125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 123225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 123837187916a486504acaf83bea30147eb5fbf46ae5James Dong return (void *) err; 123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 12423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("getNalUnitType: %d", byte); 12433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 12453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 12463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 12473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 12493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 12503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("findNextStartCode: %p %d", data, length); 12523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 12543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 12553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 12563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 12573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 12593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 12603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 12623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 12633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 12653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 12663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("parseParamSet"); 12683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 12693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 12703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 12723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 12733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 12743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Param set is malformed, since its length is 0"); 12753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 12763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 12793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 12803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 12813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Seq parameter set malformed"); 12823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 12833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 12853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 12863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 12873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 12883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 12893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 12903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 12913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 12923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Inconsistent profile/level found in seq parameter sets"); 12933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 12943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 12973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 12983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 12993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 13013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 13023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 13043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 13053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("copyAVCCodecSpecificData"); 13063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 13083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 13093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 13103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Codec specific data length too short: %d", size); 13113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 13153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 13163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 13173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 13183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 13193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 13213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 13223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("parseAVCCodecSpecificData"); 13243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 13253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 13263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 13273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 13283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 13293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 13303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 13313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 13323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 13333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 13343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 13353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 13363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 13373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 13383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 13393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("SPS must come before PPS"); 13403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 13433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 13443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 13463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 13473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 13483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("SPS must come before PPS"); 13493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 13523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 13533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 13553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 13563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Only SPS and PPS Nal units are expected"); 13573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 13613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 13653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 13663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 13673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 13683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 13713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 13723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 13733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 13743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Cound not find sequence parameter set"); 13753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 13793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 13803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 13853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 13863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 13873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 13883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Cound not find picture parameter set"); 13893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 13923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Too many pic parameter sets (%d) found", nPicParamSets); 13933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 13983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 13993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 14003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 14013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 14023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 14033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 14043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 14083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 1409548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 141003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 141103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 1412548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 141303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 1414548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Already have codec specific data"); 141503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 141603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 141703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 14193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Codec specific data length too short: %d", size); 142003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 142103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 142203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 14243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 14253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 142603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 142703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 142903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 143003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 143103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 14333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 143403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 143503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 14363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 14373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 14383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 14393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 144003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 1442b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 1443b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 1444b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 1445b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 1446b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 144703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 14493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 14503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 14513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 14523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 14533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 14543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 14553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 14563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 14573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 14583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 14603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 14613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 14623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 14653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 14663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 14673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 14683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 14693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 14703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 14713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 14723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 14733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 14743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 14763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 14773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 14783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 147903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 148003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 148103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 148203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1483872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 1484872a481558350634a3fd5cb67939de288af00ecbJames Dong* The video track's media time adjustment for real-time applications 1485872a481558350634a3fd5cb67939de288af00ecbJames Dong* is described as follows: 1486872a481558350634a3fd5cb67939de288af00ecbJames Dong* 1487872a481558350634a3fd5cb67939de288af00ecbJames Dong* First, the media time adjustment is done for every period of 1488872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs. kVideoMediaTimeAdjustPeriodTimeUs 1489872a481558350634a3fd5cb67939de288af00ecbJames Dong* is currently a fixed value chosen heuristically. The value of 1490872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs should not be very large or very small 1491872a481558350634a3fd5cb67939de288af00ecbJames Dong* for two considerations: on one hand, a relatively large value 1492872a481558350634a3fd5cb67939de288af00ecbJames Dong* helps reduce large fluctuation of drift time in the audio encoding 1493872a481558350634a3fd5cb67939de288af00ecbJames Dong* path; while on the other hand, a relatively small value helps keep 1494872a481558350634a3fd5cb67939de288af00ecbJames Dong* restoring synchronization in audio/video more frequently. Note for the 1495872a481558350634a3fd5cb67939de288af00ecbJames Dong* very first period of kVideoMediaTimeAdjustPeriodTimeUs, there is 1496872a481558350634a3fd5cb67939de288af00ecbJames Dong* no media time adjustment for the video track. 1497872a481558350634a3fd5cb67939de288af00ecbJames Dong* 1498872a481558350634a3fd5cb67939de288af00ecbJames Dong* Second, the total accumulated audio track time drift found 1499872a481558350634a3fd5cb67939de288af00ecbJames Dong* in a period of kVideoMediaTimeAdjustPeriodTimeUs is distributed 1500872a481558350634a3fd5cb67939de288af00ecbJames Dong* over a stream of incoming video frames. The number of video frames 1501872a481558350634a3fd5cb67939de288af00ecbJames Dong* affected is determined based on the number of recorded video frames 1502872a481558350634a3fd5cb67939de288af00ecbJames Dong* within the past kVideoMediaTimeAdjustPeriodTimeUs period. 1503872a481558350634a3fd5cb67939de288af00ecbJames Dong* We choose to distribute the drift time over only a portion 1504872a481558350634a3fd5cb67939de288af00ecbJames Dong* (rather than all) of the total number of recorded video frames 1505872a481558350634a3fd5cb67939de288af00ecbJames Dong* in order to make sure that the video track media time adjustment is 1506872a481558350634a3fd5cb67939de288af00ecbJames Dong* completed for the current period before the next video track media 1507872a481558350634a3fd5cb67939de288af00ecbJames Dong* time adjustment period starts. Currently, the portion chosen is a 1508872a481558350634a3fd5cb67939de288af00ecbJames Dong* half (0.5). 1509872a481558350634a3fd5cb67939de288af00ecbJames Dong* 1510872a481558350634a3fd5cb67939de288af00ecbJames Dong* Last, various additional checks are performed to ensure that 1511872a481558350634a3fd5cb67939de288af00ecbJames Dong* the actual audio encoding path does not have too much drift. 1512872a481558350634a3fd5cb67939de288af00ecbJames Dong* In particular, 1) we want to limit the average incremental time 1513872a481558350634a3fd5cb67939de288af00ecbJames Dong* adjustment for each video frame to be less than a threshold 1514872a481558350634a3fd5cb67939de288af00ecbJames Dong* for a single period of kVideoMediaTimeAdjustPeriodTimeUs. 1515872a481558350634a3fd5cb67939de288af00ecbJames Dong* Currently, the threshold is set to 5 ms. If the average incremental 1516872a481558350634a3fd5cb67939de288af00ecbJames Dong* media time adjustment for a video frame is larger than the 1517872a481558350634a3fd5cb67939de288af00ecbJames Dong* threshold, the audio encoding path has too much time drift. 1518872a481558350634a3fd5cb67939de288af00ecbJames Dong* 2) We also want to limit the total time drift in the audio 1519872a481558350634a3fd5cb67939de288af00ecbJames Dong* encoding path to be less than a threshold for a period of 1520872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs. Currently, the threshold 1521872a481558350634a3fd5cb67939de288af00ecbJames Dong* is 0.5% of kVideoMediaTimeAdjustPeriodTimeUs. If the time drift of 1522872a481558350634a3fd5cb67939de288af00ecbJames Dong* the audio encoding path is larger than the threshold, the audio 1523872a481558350634a3fd5cb67939de288af00ecbJames Dong* encoding path has too much time drift. We treat the large time 1524872a481558350634a3fd5cb67939de288af00ecbJames Dong* drift of the audio encoding path as errors, since there is no 1525872a481558350634a3fd5cb67939de288af00ecbJames Dong* way to keep audio/video in synchronization for real-time 1526872a481558350634a3fd5cb67939de288af00ecbJames Dong* applications if the time drift is too large unless we drop some 1527872a481558350634a3fd5cb67939de288af00ecbJames Dong* video frames, which has its own problems that we don't want 1528872a481558350634a3fd5cb67939de288af00ecbJames Dong* to get into for the time being. 1529872a481558350634a3fd5cb67939de288af00ecbJames Dong*/ 1530872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::adjustMediaTime(int64_t *timestampUs) { 1531872a481558350634a3fd5cb67939de288af00ecbJames Dong if (*timestampUs - mPrevMediaTimeAdjustTimestampUs >= 1532872a481558350634a3fd5cb67939de288af00ecbJames Dong kVideoMediaTimeAdjustPeriodTimeUs) { 1533872a481558350634a3fd5cb67939de288af00ecbJames Dong 1534872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGV("New media time adjustment period at %lld us", *timestampUs); 1535872a481558350634a3fd5cb67939de288af00ecbJames Dong mIsMediaTimeAdjustmentOn = true; 1536872a481558350634a3fd5cb67939de288af00ecbJames Dong mMediaTimeAdjustNumFrames = 1537872a481558350634a3fd5cb67939de288af00ecbJames Dong (mNumSamples - mPrevMediaTimeAdjustSample) >> 1; 1538872a481558350634a3fd5cb67939de288af00ecbJames Dong 1539872a481558350634a3fd5cb67939de288af00ecbJames Dong mPrevMediaTimeAdjustTimestampUs = *timestampUs; 1540872a481558350634a3fd5cb67939de288af00ecbJames Dong mPrevMediaTimeAdjustSample = mNumSamples; 1541872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t totalAccumDriftTimeUs = mOwner->getDriftTimeUs(); 1542872a481558350634a3fd5cb67939de288af00ecbJames Dong mTotalDriftTimeToAdjustUs = 1543872a481558350634a3fd5cb67939de288af00ecbJames Dong totalAccumDriftTimeUs - mPrevTotalAccumDriftTimeUs; 1544872a481558350634a3fd5cb67939de288af00ecbJames Dong 1545872a481558350634a3fd5cb67939de288af00ecbJames Dong mPrevTotalAccumDriftTimeUs = totalAccumDriftTimeUs; 1546872a481558350634a3fd5cb67939de288af00ecbJames Dong 1547872a481558350634a3fd5cb67939de288af00ecbJames Dong // Check on incremental adjusted time per frame 1548872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t adjustTimePerFrameUs = 1549872a481558350634a3fd5cb67939de288af00ecbJames Dong mTotalDriftTimeToAdjustUs / mMediaTimeAdjustNumFrames; 1550872a481558350634a3fd5cb67939de288af00ecbJames Dong 1551872a481558350634a3fd5cb67939de288af00ecbJames Dong if (adjustTimePerFrameUs < 0) { 1552872a481558350634a3fd5cb67939de288af00ecbJames Dong adjustTimePerFrameUs = -adjustTimePerFrameUs; 1553872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1554872a481558350634a3fd5cb67939de288af00ecbJames Dong if (adjustTimePerFrameUs >= 5000) { 1555872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGE("Adjusted time per video frame is %lld us", 1556872a481558350634a3fd5cb67939de288af00ecbJames Dong adjustTimePerFrameUs); 1557872a481558350634a3fd5cb67939de288af00ecbJames Dong CHECK(!"Video frame time adjustment is too large!"); 1558872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1559872a481558350634a3fd5cb67939de288af00ecbJames Dong 1560872a481558350634a3fd5cb67939de288af00ecbJames Dong // Check on total accumulated time drift within a period of 1561872a481558350634a3fd5cb67939de288af00ecbJames Dong // kVideoMediaTimeAdjustPeriodTimeUs. 1562872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftPercentage = (mTotalDriftTimeToAdjustUs * 1000) 1563872a481558350634a3fd5cb67939de288af00ecbJames Dong / kVideoMediaTimeAdjustPeriodTimeUs; 1564872a481558350634a3fd5cb67939de288af00ecbJames Dong 1565872a481558350634a3fd5cb67939de288af00ecbJames Dong if (driftPercentage < 0) { 1566872a481558350634a3fd5cb67939de288af00ecbJames Dong driftPercentage = -driftPercentage; 1567872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1568872a481558350634a3fd5cb67939de288af00ecbJames Dong if (driftPercentage > 5) { 1569872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGE("Audio track has time drift %lld us over %lld us", 1570872a481558350634a3fd5cb67939de288af00ecbJames Dong mTotalDriftTimeToAdjustUs, 1571872a481558350634a3fd5cb67939de288af00ecbJames Dong kVideoMediaTimeAdjustPeriodTimeUs); 1572872a481558350634a3fd5cb67939de288af00ecbJames Dong 1573872a481558350634a3fd5cb67939de288af00ecbJames Dong CHECK(!"The audio track media time drifts too much!"); 1574872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1575872a481558350634a3fd5cb67939de288af00ecbJames Dong 1576872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1577872a481558350634a3fd5cb67939de288af00ecbJames Dong 1578872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsMediaTimeAdjustmentOn) { 1579872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mNumSamples - mPrevMediaTimeAdjustSample <= 1580872a481558350634a3fd5cb67939de288af00ecbJames Dong mMediaTimeAdjustNumFrames) { 1581872a481558350634a3fd5cb67939de288af00ecbJames Dong 1582872a481558350634a3fd5cb67939de288af00ecbJames Dong // Do media time incremental adjustment 1583872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t incrementalAdjustTimeUs = 1584872a481558350634a3fd5cb67939de288af00ecbJames Dong (mTotalDriftTimeToAdjustUs * 1585872a481558350634a3fd5cb67939de288af00ecbJames Dong (mNumSamples - mPrevMediaTimeAdjustSample)) 1586872a481558350634a3fd5cb67939de288af00ecbJames Dong / mMediaTimeAdjustNumFrames; 1587872a481558350634a3fd5cb67939de288af00ecbJames Dong 1588872a481558350634a3fd5cb67939de288af00ecbJames Dong *timestampUs += 1589872a481558350634a3fd5cb67939de288af00ecbJames Dong (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs); 1590872a481558350634a3fd5cb67939de288af00ecbJames Dong 1591872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGV("Incremental video frame media time adjustment: %lld us", 1592872a481558350634a3fd5cb67939de288af00ecbJames Dong (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs)); 1593872a481558350634a3fd5cb67939de288af00ecbJames Dong } else { 1594872a481558350634a3fd5cb67939de288af00ecbJames Dong // Within the remaining adjustment period, 1595872a481558350634a3fd5cb67939de288af00ecbJames Dong // no incremental adjustment is needed. 1596872a481558350634a3fd5cb67939de288af00ecbJames Dong *timestampUs += 1597872a481558350634a3fd5cb67939de288af00ecbJames Dong (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs); 1598872a481558350634a3fd5cb67939de288af00ecbJames Dong 1599872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGV("Fixed video frame media time adjustment: %lld us", 1600872a481558350634a3fd5cb67939de288af00ecbJames Dong (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs)); 1601872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1602872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1603872a481558350634a3fd5cb67939de288af00ecbJames Dong} 1604872a481558350634a3fd5cb67939de288af00ecbJames Dong 1605872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 1606872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 1607872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 1608872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 1609872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 1610872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 1611872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 1612872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 1613872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 1614872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 1615872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 1616872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 1617872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 1618872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 1619872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1620872a481558350634a3fd5cb67939de288af00ecbJames Dong} 1621872a481558350634a3fd5cb67939de288af00ecbJames Dong 162237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 162330ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 162413aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 162513aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 162613aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 162713aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 16288f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t lastTimestampUs = 0; // Previous sample time stamp in ms 16298f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t lastDurationUs = 0; // Between the previous two samples in ms 1630c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t currDurationTicks = 0; // Timescale based ticks 1631c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t lastDurationTicks = 0; // Timescale based ticks 16328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 1633be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 1634a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 16351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t timestampUs; 1636e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1637a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 1638a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 1639a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } else { 1640a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 1641a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 1642d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 164320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1644ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mNumSamples = 0; 164593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 164620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 164793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 164820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 164920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 165020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 165113aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 165220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 165320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 165420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1655a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 1656a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 1657a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 1658a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 1659a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 1660a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 1661a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 1662a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1663a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 166430ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 166530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 166603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 166703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 166803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 1669548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 1670548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 16711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 167203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 167303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 167403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 167503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 1676be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 16771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 167803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 167903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 168003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 168103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 168203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 168303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 168430ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 168530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 168630ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 168730ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 168830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1689548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 169030ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 1691a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1692a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1693d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 1694d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 1695d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 1696d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 1697d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 1698d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 1699d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 1700d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 1701d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 1702d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 17031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 1704e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 1705b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 1706b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mIsAvc) { 1707b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 1708b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 1709b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 1710b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 1711b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 1712b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 1713050b28a593350047845a45a14cc5026221ac1620James Dong 1714d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 17151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 17161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 17171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1718d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 1719d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 1720d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1721d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1722d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 1723d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 1724d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1725d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1726d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1727050b28a593350047845a45a14cc5026221ac1620James Dong 1728d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 1729d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 1730d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 17318428af5381e835cc783b7ecb0d71cb60961c99c2James Dong /* 17328428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * The original timestamp found in the data buffer will be modified as below: 17338428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * 17348428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * There is a playback offset into this track if the track's start time 17358428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * is not the same as the movie start time, which will be recorded in edst 17368428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * box of the output file. The playback offset is to make sure that the 17378428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * starting time of the audio/video tracks are synchronized. Although the 17388428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * track's media timestamp may be subject to various modifications 17398428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * as outlined below, the track's playback offset time remains unchanged 17408428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * once the first data buffer of the track is received. 17418428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * 17428428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * The media time stamp will be calculated by subtracting the playback offset 17438428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * (and potential pause durations) from the original timestamp in the buffer. 17448428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * 17458428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * If this track is a video track for a real-time recording application with 17468428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * both audio and video tracks, its media timestamp will subject to further 17478428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * modification based on the media clock of the audio track. This modification 17488428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * is needed for the purpose of maintaining good audio/video synchronization. 17498428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * 17508428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * If the recording session is paused and resumed multiple times, the track 17518428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * media timestamp will be modified as if the recording session had never been 17528428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * paused at all during playback of the recorded output file. In other words, 17538428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * the output file will have no memory of pause/resume durations. 17548428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * 17558428af5381e835cc783b7ecb0d71cb60961c99c2James Dong */ 1756d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 17578428af5381e835cc783b7ecb0d71cb60961c99c2James Dong LOGV("%s timestampUs: %lld", mIsAudio? "Audio": "Video", timestampUs); 1758d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1759d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 17608644c14618d30d9e57a69df40ed939986ebf02c4James Dong if (mSampleSizes.empty()) { 1761f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 1762f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 17638428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 17643c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 176548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 1766a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 17678428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 17688428af5381e835cc783b7ecb0d71cb60961c99c2James Dong CHECK(durExcludingEarlierPausesUs >= 0); 17698428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 17708428af5381e835cc783b7ecb0d71cb60961c99c2James Dong CHECK(pausedDurationUs >= lastDurationUs); 17718428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 1772a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 1773a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1774a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1775a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 17768428af5381e835cc783b7ecb0d71cb60961c99c2James Dong CHECK(timestampUs >= 0); 1777872a481558350634a3fd5cb67939de288af00ecbJames Dong 1778872a481558350634a3fd5cb67939de288af00ecbJames Dong // Media time adjustment for real-time applications 1779872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsRealTimeRecording) { 1780872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 1781872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 1782872a481558350634a3fd5cb67939de288af00ecbJames Dong } else { 1783872a481558350634a3fd5cb67939de288af00ecbJames Dong adjustMediaTime(×tampUs); 1784e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1785e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1786872a481558350634a3fd5cb67939de288af00ecbJames Dong 1787e259531ce59ab1f31de5a23124b22536f6a5a767James Dong CHECK(timestampUs >= 0); 1788e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (mNumSamples > 1) { 1789e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (timestampUs <= lastTimestampUs) { 17904f86a980fee1880dca61b828599fa6d76755a485James Dong LOGW("Frame arrives too late!"); 17914f86a980fee1880dca61b828599fa6d76755a485James Dong // Don't drop the late frame, since dropping a frame may cause 17924f86a980fee1880dca61b828599fa6d76755a485James Dong // problems later during playback 17934f86a980fee1880dca61b828599fa6d76755a485James Dong 17944f86a980fee1880dca61b828599fa6d76755a485James Dong // The idea here is to avoid having two or more samples with the 17954f86a980fee1880dca61b828599fa6d76755a485James Dong // same timestamp in the output file. 17964f86a980fee1880dca61b828599fa6d76755a485James Dong if (mTimeScale >= 1000000LL) { 179740e9940fadf22daa64c1e766fa8a855c7b149c17James Dong timestampUs = lastTimestampUs + 1; 17984f86a980fee1880dca61b828599fa6d76755a485James Dong } else { 179940e9940fadf22daa64c1e766fa8a855c7b149c17James Dong timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale; 18004f86a980fee1880dca61b828599fa6d76755a485James Dong } 1801e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1802e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1803e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 18048428af5381e835cc783b7ecb0d71cb60961c99c2James Dong LOGV("%s media time stamp: %lld and previous paused duration %lld", 18058428af5381e835cc783b7ecb0d71cb60961c99c2James Dong mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs); 1806c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 1807c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 18083b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 18093b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 18108644c14618d30d9e57a69df40ed939986ebf02c4James Dong mSampleSizes.push_back(sampleSize); 1811ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong ++mNumSamples; 1812ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples > 2) { 1813c059860c73678a202bfa33062723e8f82fb779d9James Dong // We need to use the time scale based ticks, rather than the 1814c059860c73678a202bfa33062723e8f82fb779d9James Dong // timestamp itself to determine whether we have to use a new 1815c059860c73678a202bfa33062723e8f82fb779d9James Dong // stts entry, since we may have rounding errors. 1816c059860c73678a202bfa33062723e8f82fb779d9James Dong // The calculation is intended to reduce the accumulated 1817c059860c73678a202bfa33062723e8f82fb779d9James Dong // rounding errors. 1818c059860c73678a202bfa33062723e8f82fb779d9James Dong currDurationTicks = 1819c059860c73678a202bfa33062723e8f82fb779d9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 1820c059860c73678a202bfa33062723e8f82fb779d9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 1821c059860c73678a202bfa33062723e8f82fb779d9James Dong 1822c059860c73678a202bfa33062723e8f82fb779d9James Dong if (currDurationTicks != lastDurationTicks) { 18231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneSttsTableEntry(sampleCount, lastDurationUs); 1824be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 1825be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1826be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 1827be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1828be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1829be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 1830ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples >= 2 && previousSampleSize != sampleSize) { 1831be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 1832be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 18338644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 1834be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 18358644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 1836c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 18378644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 183820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1839d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 18401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStssTableEntry(mNumSamples); 1841d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 1842d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 184393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 184493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 184593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 184693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 1847faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 184893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 184958ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mOwner->numTracks() == 1) { 18501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 185158ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 185258ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mChunkOffsets.empty()) { 18531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 185458ae9c530247668f8af36e30d228c716c226b3d4James Dong } 185558ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 185658ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 185758ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 185858ae9c530247668f8af36e30d228c716c226b3d4James Dong } 185913aec890216948b0c364f8f92792129d0335f506James Dong 186013aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 186113aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 18621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 18631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 186413aec890216948b0c364f8f92792129d0335f506James Dong } else { 186513aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 186613aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 186713aec890216948b0c364f8f92792129d0335f506James Dong } else { 186813aec890216948b0c364f8f92792129d0335f506James Dong if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 186913aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 187013aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 187113aec890216948b0c364f8f92792129d0335f506James Dong (--(mStscTableEntries.end()))->samplesPerChunk != 187213aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size()) { 18731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(nChunks, mChunkSamples.size()); 187413aec890216948b0c364f8f92792129d0335f506James Dong } 18751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 187613aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 187713aec890216948b0c364f8f92792129d0335f506James Dong } 187813aec890216948b0c364f8f92792129d0335f506James Dong } 187913aec890216948b0c364f8f92792129d0335f506James Dong } 188013aec890216948b0c364f8f92792129d0335f506James Dong 188120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 188225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1883a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong if (mSampleSizes.empty() || // no samples written 1884a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong (!mIsAudio && mNumStssTableEntries == 0) || // no sync frames for video 1885a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong (OK != checkCodecSpecificData())) { // no codec specific data 1886690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 1887f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 1888faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong mOwner->trackProgressStatus(this, -1, err); 1889be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 189013aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 189158ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mOwner->numTracks() == 1) { 18921f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(1, mNumSamples); 189358ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 18941f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 18951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 189613aec890216948b0c364f8f92792129d0335f506James Dong } 189713aec890216948b0c364f8f92792129d0335f506James Dong 1898be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 1899be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 1900be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 1901ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples == 1) { 19028f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 1903be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1904be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 1905be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 19061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneSttsTableEntry(sampleCount, lastDurationUs); 1907c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 190825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 19091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 19101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video"); 1911872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 1912872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs()); 1913872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1914365a963142093a1cd8efdcea76b5f65096a5b115James Dong 191537187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 191637187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 191737187916a486504acaf83bea30147eb5fbf46ae5James Dong } 191837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 1919365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1920365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1921faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 1922faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong LOGV("trackProgressStatus: %lld us", timeUs); 1923215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 1924215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 192593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Fire time tracking progress status at %lld us", timeUs); 1926faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err); 192793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 192893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 192993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 193093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1931faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 1932faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong const MPEG4Writer::Track* track, int64_t timeUs, status_t err) { 1933faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 1934faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong int32_t nTracks = mTracks.size(); 1935faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong CHECK(nTracks >= 1); 1936faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong CHECK(nTracks < 64); // Arbitrary number 1937faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1938faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong int32_t trackNum = 0; 1939faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong CHECK(trackNum < nTracks); 1940faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum <<= 16; 1941faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1942faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 1943faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 1944faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 1945faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong notify(MEDIA_RECORDER_EVENT_ERROR, 1946faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum | MEDIA_RECORDER_ERROR_UNKNOWN, 1947faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 1948faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 1949faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 1950faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1951faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 1952faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 1953faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong notify(MEDIA_RECORDER_EVENT_INFO, 1954faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS, 1955faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 1956faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 1957faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 1958faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 1959faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong notify(MEDIA_RECORDER_EVENT_INFO, 1960faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS, 1961faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 1962faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 1963faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 1964faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1965d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 1966d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong LOGV("setDriftTimeUs: %lld us", driftTimeUs); 1967e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 1968d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 1969e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 1970e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1971e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 1972e259531ce59ab1f31de5a23124b22536f6a5a767James Dong LOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 1973e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 1974e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 1975e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 1976e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1977b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 1978b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 1979b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 1980b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 19811c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 19821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("bufferChunk"); 19831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 19841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 19851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 198613aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 198720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 198820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19893b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 1990c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 199120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 199220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1993d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 1994d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 1995d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1996d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1997690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 1998690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 1999690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2000690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2001690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2002690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2003690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2004690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 2005a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong LOGE("Missing codec specific data"); 2006690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2007690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2008690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2009690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2010690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 2011a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong LOGE("Unexepected codec specific data found"); 2012690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2013690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2014690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2015690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2016690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2017690f546b0ee548dbfe997df36418e5302ec2d786James Dong 20181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader( 20191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t trackID, bool use32BitOffset) { 202020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 202120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findCString(kKeyMIMEType, &mime); 20220c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 202320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("%s track time scale: %d", 20251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 20268f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 202720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 20288f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 20298f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 203020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 203120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("trak"); 203220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 203320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("tkhd"); 20341acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Flags = 7 to indicate that the track is enabled, and 20351acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // part of the presentation 20361acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0x07); // version=0, flags=7 203720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 203820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 203920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(trackID); 204020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 20418f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t tkhdDuration = 20428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 20438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 204420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 204520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 204620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // layer 204720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // alternate group 20481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 204920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 205020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 205120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); // matrix 205220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 205320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 205420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 205520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); 205620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 205720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 205820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 205920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x40000000); 206020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAudio) { 206220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 206320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 206420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 206520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 206620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 206720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 20680c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 206920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2070050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2071050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 207220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 207320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // tkhd 207420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2075f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2076f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (mStartTimestampUs != moovStartTimeUs) { 20773c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("edts"); 20783c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("elst"); 20791acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0); // version=0, flags=0: 32-bit time 20801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(2); // never ends with an empty list 20818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 20828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // First elst entry: specify the starting time offset 20838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t offsetUs = mStartTimestampUs - moovStartTimeUs; 20848428af5381e835cc783b7ecb0d71cb60961c99c2James Dong LOGV("OffsetUs: %lld", offsetUs); 20858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6; 20868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(seg); // in mvhd timecale 20878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(-1); // starting time offset 20888f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(1 << 16); // rate = 1.0 20898f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 20908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // Second elst entry: specify the track duration 20918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 20928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(seg); // in mvhd timescale 20931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0); 20941acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); 20953c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 20963c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 20973c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 20983c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 209920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdia"); 210020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 210120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdhd"); 210220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 210320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 210420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 21058f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(mTimeScale); // media timescale 21068f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 21078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(mdhdDuration); // use media timescale 21081acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Language follows the three letter standard ISO-639-2/T 21091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // 'e', 'n', 'g' for "English", for instance. 21101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Each character is packed as the difference between its ASCII value and 0x60. 21111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // For "English", these are 00101, 01110, 00111. 21121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // XXX: Where is the padding bit located: 0x15C7? 21131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt16(0); // language code 211420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 211520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 211620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 211720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("hdlr"); 211820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 2119050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // component type: should be mhlr 21201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 212120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 212220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 212320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 21241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Removing "r" for the name string just makes the string 4 byte aligned 21251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 212620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 212720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 212820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("minf"); 21291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAudio) { 213020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("smhd"); 213120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 213220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // balance 213320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 213420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 213520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 213620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("vmhd"); 21371acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0x01); // version=0, flags=1 213820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // graphics mode 213920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // opcolor 214020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 214120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 214220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 214320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 2144050b28a593350047845a45a14cc5026221ac1620James Dong 2145050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dinf"); 2146050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dref"); 2147050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 21481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1); // entry count (either url or urn) 21491acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // The table index here refers to the sample description index 21501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // in the sample table entries. 2151050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("url "); 21521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2153050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // url 2154050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dref 2155050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dinf 2156050b28a593350047845a45a14cc5026221ac1620James Dong 215720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stbl"); 215820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 215920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsd"); 216020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 216120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); // entry count 21621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAudio) { 216325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber const char *fourcc = NULL; 216418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 216525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "samr"; 216618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 216725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "sawb"; 2168050b28a593350047845a45a14cc5026221ac1620James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2169050b28a593350047845a45a14cc5026221ac1620James Dong fourcc = "mp4a"; 217025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } else { 217125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 217225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber CHECK(!"should not be here, unknown mime type."); 217325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 217425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 217525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mOwner->beginBox(fourcc); // audio format 217620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 217720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 2178050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x1); // data ref index 217920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 218020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 2181050b28a593350047845a45a14cc5026221ac1620James Dong int32_t nChannels; 2182050b28a593350047845a45a14cc5026221ac1620James Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2183050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(nChannels); // channel count 218420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(16); // sample size 218520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 218620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 218720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 218820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t samplerate; 218920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 21900c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 219120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(samplerate << 16); 2192050b28a593350047845a45a14cc5026221ac1620James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2193050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("esds"); 219451dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong CHECK(mCodecSpecificData); 219551dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong CHECK(mCodecSpecificDataSize > 0); 2196050b28a593350047845a45a14cc5026221ac1620James Dong 21975f995b0e72ed6f186cb0ab2a525c4cfce614f3a9Andreas Huber // Make sure all sizes encode to a single byte. 21985f995b0e72ed6f186cb0ab2a525c4cfce614f3a9Andreas Huber CHECK(mCodecSpecificDataSize + 23 < 128); 21995f995b0e72ed6f186cb0ab2a525c4cfce614f3a9Andreas Huber 2200050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 2201050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x03); // ES_DescrTag 2202050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2203050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x0000);// ES_ID 2204050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); 2205050b28a593350047845a45a14cc5026221ac1620James Dong 2206050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2207050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2208050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2209050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x15); // streamType AudioStream 2210050b28a593350047845a45a14cc5026221ac1620James Dong 2211050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x03); // XXX 2212050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2213050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // max bit rate 2214050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // avg bit rate 2215050b28a593350047845a45a14cc5026221ac1620James Dong 2216050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2217050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(mCodecSpecificDataSize); 2218050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2219050b28a593350047845a45a14cc5026221ac1620James Dong 2220050b28a593350047845a45a14cc5026221ac1620James Dong static const uint8_t kData2[] = { 2221050b28a593350047845a45a14cc5026221ac1620James Dong 0x06, // SLConfigDescriptorTag 2222050b28a593350047845a45a14cc5026221ac1620James Dong 0x01, 2223050b28a593350047845a45a14cc5026221ac1620James Dong 0x02 2224050b28a593350047845a45a14cc5026221ac1620James Dong }; 2225050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(kData2, sizeof(kData2)); 2226050b28a593350047845a45a14cc5026221ac1620James Dong 2227050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // esds 22285aff464f67322cd13dc8ed165806971cfff2e4d5James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 22295aff464f67322cd13dc8ed165806971cfff2e4d5James Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 22305aff464f67322cd13dc8ed165806971cfff2e4d5James Dong // 3gpp2 Spec AMRSampleEntry fields 22315aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->beginBox("damr"); 22325aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeCString(" "); // vendor: 4 bytes 22335aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt8(0); // decoder version 22345aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 22355aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt8(0); // mode change period 22365aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt8(1); // frames per sample 22375aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->endBox(); 2238050b28a593350047845a45a14cc5026221ac1620James Dong } 223920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 224020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 224118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 224220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mp4v"); 224318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 224420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("s263"); 224530ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 224630ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avc1"); 224720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 224825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 22490c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!"should not be here, unknown mime type."); 225020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 225120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 225220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 225320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 22541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt16(1); // data ref index 225520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 225620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 225720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 225820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 225920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 226020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 226120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 226220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 226320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 22640c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 226520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 226620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(width); 226720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(height); 226820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // horiz resolution 226920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // vert resolution 227020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 227120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(1); // frame count 227220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(" ", 32); 227320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x18); // depth 227420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(-1); // predefined 227520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22760c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(23 + mCodecSpecificDataSize < 128); 227720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 227818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2279a37923e9a57d489e7bed2129369219039fa5f12cJames Dong CHECK(mCodecSpecificData); 2280a37923e9a57d489e7bed2129369219039fa5f12cJames Dong CHECK(mCodecSpecificDataSize > 0); 228120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("esds"); 228220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 228320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 228420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 228520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x03); // ES_DescrTag 228620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(23 + mCodecSpecificDataSize); 228720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x0000); // ES_ID 228820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x1f); 228920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 229020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x04); // DecoderConfigDescrTag 229120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(15 + mCodecSpecificDataSize); 229220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 229320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x11); // streamType VisualStream 229420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 229520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData[] = { 229620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 0x77, 0x00, 229720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00, 229820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00 229920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 230020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData, sizeof(kData)); 2301050b28a593350047845a45a14cc5026221ac1620James Dong 230220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 230320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 230420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(mCodecSpecificDataSize); 230520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 230620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 230720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData2[] = { 230820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x06, // SLConfigDescriptorTag 230920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 231020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x02 231120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 231220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData2, sizeof(kData2)); 231320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 231420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // esds 231518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 231620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("d263"); 231720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 231820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // vendor 231920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // decoder version 232020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(10); // level: 10 232120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // profile: 0 232220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 232320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // d263 232430ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 232551dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong CHECK(mCodecSpecificData); 232695fcef25b48e35b625899288971ab628efbf8584Andreas Huber CHECK(mCodecSpecificDataSize >= 5); 232795fcef25b48e35b625899288971ab628efbf8584Andreas Huber 232895fcef25b48e35b625899288971ab628efbf8584Andreas Huber // Patch avcc's lengthSize field to match the number 232995fcef25b48e35b625899288971ab628efbf8584Andreas Huber // of bytes we use to indicate the size of a nal unit. 233095fcef25b48e35b625899288971ab628efbf8584Andreas Huber uint8_t *ptr = (uint8_t *)mCodecSpecificData; 233195fcef25b48e35b625899288971ab628efbf8584Andreas Huber ptr[4] = 233295fcef25b48e35b625899288971ab628efbf8584Andreas Huber (ptr[4] & 0xfc) 233395fcef25b48e35b625899288971ab628efbf8584Andreas Huber | (mOwner->useNalLengthFour() ? 3 : 1); 233495fcef25b48e35b625899288971ab628efbf8584Andreas Huber 233530ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avcC"); 233630ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 233730ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // avcC 233820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 233930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 23401acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->beginBox("pasp"); 23411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // This is useful if the pixel is not square 23421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // hspacing 23431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // vspacing 23441acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->endBox(); // pasp 234530ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // mp4v, s263 or avc1 234620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 234720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsd 234820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 234920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stts"); 235020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 23511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mOwner->writeInt32(mNumSttsTableEntries); 2352c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t prevTimestampUs = 0; 2353be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 2354be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSttsTableEntries.end(); ++it) { 2355be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleCount); 2356c059860c73678a202bfa33062723e8f82fb779d9James Dong 2357c059860c73678a202bfa33062723e8f82fb779d9James Dong // Make sure that we are calculating the sample duration the exactly 2358c059860c73678a202bfa33062723e8f82fb779d9James Dong // same way as we made decision on how to create stts entries. 2359c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs; 2360c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL - 2361c059860c73678a202bfa33062723e8f82fb779d9James Dong (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2362c059860c73678a202bfa33062723e8f82fb779d9James Dong prevTimestampUs += (it->sampleCount * it->sampleDurationUs); 2363c059860c73678a202bfa33062723e8f82fb779d9James Dong 23648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(dur); 236520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 236620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stts 236720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!mIsAudio) { 2369050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("stss"); 2370050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 23711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mOwner->writeInt32(mNumStssTableEntries); // number of sync frames 2372050b28a593350047845a45a14cc5026221ac1620James Dong for (List<int32_t>::iterator it = mStssTableEntries.begin(); 2373050b28a593350047845a45a14cc5026221ac1620James Dong it != mStssTableEntries.end(); ++it) { 2374050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(*it); 2375050b28a593350047845a45a14cc5026221ac1620James Dong } 2376050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // stss 2377050b28a593350047845a45a14cc5026221ac1620James Dong } 2378050b28a593350047845a45a14cc5026221ac1620James Dong 237920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsz"); 238020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 2381be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 23828644c14618d30d9e57a69df40ed939986ebf02c4James Dong List<size_t>::iterator it = mSampleSizes.begin(); 23838644c14618d30d9e57a69df40ed939986ebf02c4James Dong mOwner->writeInt32(*it); // default sample size 2384be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2385be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(0); 2386be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2387ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mOwner->writeInt32(mNumSamples); 2388be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (!mSamplesHaveSameSize) { 23898644c14618d30d9e57a69df40ed939986ebf02c4James Dong for (List<size_t>::iterator it = mSampleSizes.begin(); 23908644c14618d30d9e57a69df40ed939986ebf02c4James Dong it != mSampleSizes.end(); ++it) { 23918644c14618d30d9e57a69df40ed939986ebf02c4James Dong mOwner->writeInt32(*it); 2392be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 239320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 239420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsz 239520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 239620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsc"); 239720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 23981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mOwner->writeInt32(mNumStscTableEntries); 239913aec890216948b0c364f8f92792129d0335f506James Dong for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 240013aec890216948b0c364f8f92792129d0335f506James Dong it != mStscTableEntries.end(); ++it) { 240113aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->firstChunk); 240213aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->samplesPerChunk); 240313aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->sampleDescriptionId); 240420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 240520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsc 24061acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 240720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 24081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mOwner->writeInt32(mNumStcoTableEntries); 240913aec890216948b0c364f8f92792129d0335f506James Dong for (List<off_t>::iterator it = mChunkOffsets.begin(); 241013aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkOffsets.end(); ++it) { 24111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (use32BitOffset) { 24121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(static_cast<int32_t>(*it)); 24131acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 24141acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt64((*it)); 24151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 241620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 24178f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->endBox(); // stco or co64 241820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 241920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stbl 24201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->endBox(); // minf 242120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // mdia 242220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // trak 242320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 242420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 242520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 2426