MPEG4Writer.cpp revision b5212db69734962f55e1493d3e696794172ced51
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> 36674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <sys/types.h> 37674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <sys/stat.h> 38674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <fcntl.h> 39674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <unistd.h> 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h" 4219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongstatic const int64_t kMax32BitFileSize = 0x007fffffffLL; 463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07; 473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08; 4870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongstatic const int64_t kInitialDelayTimeUs = 700000LL; 495b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong 505b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong// Using longer adjustment period to suppress fluctuations in 515b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong// the audio encoding paths 525b6a01e65aa4129a9226667536d1bc1dad5980d8James Dongstatic const int64_t kVideoMediaTimeAdjustPeriodTimeUs = 600000000LL; // 10 minutes 533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 56bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId); 578f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 6137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t stop(); 6237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 6325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 653b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 66d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 67b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTrackHeader(bool use32BitOffset = true); 681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 72c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong void addChunkOffset(off64_t offset); 7370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int32_t getTrackId() const { return mTrackId; } 74dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 79693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 81a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 82a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 83eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 87bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 88c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 8943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 90e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 91e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // For realtime applications, we need to adjust the media clock 92e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // for video track based on the audio media clock 93e259531ce59ab1f31de5a23124b22536f6a5a767James Dong bool mIsRealTimeRecording; 94e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int64_t mMaxTimeStampUs; 95d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 978f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 101ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // mNumSamples is used to track how many samples in mSampleSizes List. 102ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // This is to reduce the cost associated with mSampleSizes.size() call, 103ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // since it is O(n). Ideally, the fix should be in List class. 104ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong size_t mNumSamples; 1058644c14618d30d9e57a69df40ed939986ebf02c4James Dong List<size_t> mSampleSizes; 106be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong bool mSamplesHaveSameSize; 107be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 10813aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 1091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1101f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStcoTableEntries; 111c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong List<off64_t> mChunkOffsets; 11213aec890216948b0c364f8f92792129d0335f506James Dong 1131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStscTableEntries; 11413aec890216948b0c364f8f92792129d0335f506James Dong struct StscTableEntry { 11513aec890216948b0c364f8f92792129d0335f506James Dong 11613aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 11713aec890216948b0c364f8f92792129d0335f506James Dong : firstChunk(chunk), 11813aec890216948b0c364f8f92792129d0335f506James Dong samplesPerChunk(samples), 11913aec890216948b0c364f8f92792129d0335f506James Dong sampleDescriptionId(id) {} 12013aec890216948b0c364f8f92792129d0335f506James Dong 12113aec890216948b0c364f8f92792129d0335f506James Dong uint32_t firstChunk; 12213aec890216948b0c364f8f92792129d0335f506James Dong uint32_t samplesPerChunk; 12313aec890216948b0c364f8f92792129d0335f506James Dong uint32_t sampleDescriptionId; 12413aec890216948b0c364f8f92792129d0335f506James Dong }; 12513aec890216948b0c364f8f92792129d0335f506James Dong List<StscTableEntry> mStscTableEntries; 12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1271f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStssTableEntries; 128050b28a593350047845a45a14cc5026221ac1620James Dong List<int32_t> mStssTableEntries; 129050b28a593350047845a45a14cc5026221ac1620James Dong 1301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumSttsTableEntries; 131be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong struct SttsTableEntry { 132be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 1338f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong SttsTableEntry(uint32_t count, uint32_t durationUs) 1348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong : sampleCount(count), sampleDurationUs(durationUs) {} 135be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 136be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t sampleCount; 1378f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong uint32_t sampleDurationUs; 138be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong }; 139be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SttsTableEntry> mSttsTableEntries; 140be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 1413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 1423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 1433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 1443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 1453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 1463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 1473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 1483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 1493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 1503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 1513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 1523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 1533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 1543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 157548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 15893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 1613c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 16270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 16370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 16493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 16593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 16625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 167872a481558350634a3fd5cb67939de288af00ecbJames Dong // Has the media time adjustment for video started? 168872a481558350634a3fd5cb67939de288af00ecbJames Dong bool mIsMediaTimeAdjustmentOn; 169872a481558350634a3fd5cb67939de288af00ecbJames Dong // The time stamp when previous media time adjustment period starts 170872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t mPrevMediaTimeAdjustTimestampUs; 171872a481558350634a3fd5cb67939de288af00ecbJames Dong // Number of vidoe frames whose time stamp may be adjusted 172872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t mMediaTimeAdjustNumFrames; 173872a481558350634a3fd5cb67939de288af00ecbJames Dong // The sample number when previous meida time adjustmnet period starts 174872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t mPrevMediaTimeAdjustSample; 175872a481558350634a3fd5cb67939de288af00ecbJames Dong // The total accumulated drift time within a period of 176872a481558350634a3fd5cb67939de288af00ecbJames Dong // kVideoMediaTimeAdjustPeriodTimeUs. 177872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t mTotalDriftTimeToAdjustUs; 178872a481558350634a3fd5cb67939de288af00ecbJames Dong // The total accumalated drift time since the start of the recording 179872a481558350634a3fd5cb67939de288af00ecbJames Dong // excluding the current time adjustment period 180872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t mPrevTotalAccumDriftTimeUs; 181872a481558350634a3fd5cb67939de288af00ecbJames Dong 182872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 183872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 184872a481558350634a3fd5cb67939de288af00ecbJames Dong 185872a481558350634a3fd5cb67939de288af00ecbJames Dong // Adjust the time stamp of the video track according to 186872a481558350634a3fd5cb67939de288af00ecbJames Dong // the drift time information from the audio track. 187872a481558350634a3fd5cb67939de288af00ecbJames Dong void adjustMediaTime(int64_t *timestampUs); 188872a481558350634a3fd5cb67939de288af00ecbJames Dong 18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 19037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 1933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 1943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 195b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 196b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 197b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 198215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 199215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 200faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 20193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 20203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 20319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 20419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 205c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 206c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 207c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 208c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 209c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 210c059860c73678a202bfa33062723e8f82fb779d9James Dong 211690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 212690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 21313f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t mRotation; 214690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 2161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 2171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 2181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneSttsTableEntry(size_t sampleCount, int64_t durationUs); 21943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 2201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMdhdBox(time_t now); 235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 237b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 238b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTkhdBox(time_t now); 239b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 240b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 241b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 242b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 243b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 244b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 250674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(-1), 251674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(NO_INIT), 252b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 2531acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 254a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 255a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 256a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 25813aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 2597837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 260f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong mInterleaveDurationUs(1000000) { 261674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong 26203f6f4e7e2ce09357cbc05bb546cd8a6e54b5baeJames Dong mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR); 263674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mFd >= 0) { 264674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck = OK; 265674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong } 26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26830ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 269674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(dup(fd)), 270674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(mFd < 0? NO_INIT: OK), 271b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 2721acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 273a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 274a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 275a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 27630ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 27713aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 2787837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 279f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong mInterleaveDurationUs(1000000) { 28030ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 28130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 28220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 2861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 2881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 2891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 294dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 295dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 296dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 297dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 298dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 299dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 300dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 301dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 302dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 303dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 304dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 305dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 306dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 307dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 308dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 309dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 310dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 311dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 312dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) const { 313dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 314dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 315dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 316dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 317dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 318dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 319dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 320dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 321dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 322dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 323dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 324dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 3252dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 326bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 327bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 328bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong LOGE("Attempt to add source AFTER recording is started"); 329bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 330bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 331bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Track *track = new Track(this, source, mTracks.size()); 33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 3332dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 3342dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 338a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 339a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 34093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 341a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 342a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 343a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 344a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 345a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 346a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 347a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 348a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 349a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 350a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 351a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 352a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 353a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 3542dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 3552dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 3562dec2b5be2056c6d9428897dc672185872d30d17James Dong // 3572dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 3582dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 3592dec2b5be2056c6d9428897dc672185872d30d17James Dong 36078a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 3612dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 36278a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 3632dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 3642dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 3652dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 3662dec2b5be2056c6d9428897dc672185872d30d17James Dong 3672dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 3682dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 3692dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 37078a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 3712dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 3722dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 3732dec2b5be2056c6d9428897dc672185872d30d17James Dong 37478a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 375a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 37678a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 37778a1a286f736888ae7af8860b2c424af0d978848James Dong } 37878a1a286f736888ae7af8860b2c424af0d978848James Dong 37978a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 38078a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 38178a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 38278a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 38378a1a286f736888ae7af8860b2c424af0d978848James Dong ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000); 38478a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 38578a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 38678a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 38778a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 38878a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 38978a1a286f736888ae7af8860b2c424af0d978848James Dong } 39078a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 39178a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 39278a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 39378a1a286f736888ae7af8860b2c424af0d978848James Dong } 3942dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3952dec2b5be2056c6d9428897dc672185872d30d17James Dong } 39678a1a286f736888ae7af8860b2c424af0d978848James Dong 3972dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 3982dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 3992dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4002dec2b5be2056c6d9428897dc672185872d30d17James Dong 4012dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 4022dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 4032dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 4042dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 4052dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4062dec2b5be2056c6d9428897dc672185872d30d17James Dong 407a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 4082dec2b5be2056c6d9428897dc672185872d30d17James Dong " moov size %lld bytes", 4092dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 4102dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 4112dec2b5be2056c6d9428897dc672185872d30d17James Dong} 4122dec2b5be2056c6d9428897dc672185872d30d17James Dong 4132dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 414674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 41525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 418a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 419a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 420a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 421a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 422a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 423a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 424a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 425a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 426a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 427a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 4282dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 4292dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 4302dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 4312dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 4322dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 4332dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4342dec2b5be2056c6d9428897dc672185872d30d17James Dong 4351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 4361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 4371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 4381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 4391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 4401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 4411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 4421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 4431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 444872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGW("32-bit file size limit (%lld bytes) too big. " 445d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong "It is changed to %lld bytes", 446d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 447d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 4481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 4491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 4501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 451b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 452b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 453b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 454b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 455b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 4562dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4572dec2b5be2056c6d9428897dc672185872d30d17James Dong 458065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 45993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 460a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 461a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 462a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 46393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 464a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 465a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 466a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 467a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 4688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 4698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 4708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 4718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 4728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 4738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("movie time scale: %d", mTimeScale); 4748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 4757837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = true; 4767837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 4777837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 4787837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 4797837c17063a4c50bc856ba59418516fdab731de7James Dong 480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 48120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4827837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 48320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4847837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 4852dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 4862dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 4872dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 4882dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4892dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 4907837c17063a4c50bc856ba59418516fdab731de7James Dong } 4917837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mEstimatedMoovBoxSize >= 8); 492c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 4937837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize); 4947837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 4957837c17063a4c50bc856ba59418516fdab731de7James Dong 4967837c17063a4c50bc856ba59418516fdab731de7James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 4977837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 498c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 4991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 5001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 5011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 5021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 5031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 5041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 5051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 5061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 5071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 5081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 5091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 5101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 511a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 512a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 5141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 515a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 51625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5191f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 5201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 5211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 5221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 52337187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 524674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 52537187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 526a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 527a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 52837187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 529a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 530a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 53137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 53237187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 53337187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 53437187916a486504acaf83bea30147eb5fbf46ae5James Dong } 535a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 53637187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 537a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 538a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 5391c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 540cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong LOGD("Stopping writer thread"); 5411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 5421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 5431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 5441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 5451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 5461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 5471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 5481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 5491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 5501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 551cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong LOGD("Writer thread stopped"); 5521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 5531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 55413f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 55513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 55613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 55713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 55813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 55913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 56013f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 56113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 56213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 56313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 56413f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 56513f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 56613f6284305e4b27395a23db7882d670bdb1bcae1James Dong LOGV("writeCompositionMatrix"); 56713f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 56813f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 56913f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 57013f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 57113f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 57213f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 57313f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 57413f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 57513f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 57613f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 57713f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 57813f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 57913f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 58013f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 58113f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 58213f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 58313f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 58413f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 58513f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 58613f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 58713f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 58813f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 58913f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 59013f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 59113f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 59213f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 59313f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 59413f6284305e4b27395a23db7882d670bdb1bcae1James Dong 59513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 59613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 59713f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 59813f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 59913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 60013f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 60113f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 60213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 60313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 60413f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 60513f6284305e4b27395a23db7882d670bdb1bcae1James Dong 60613f6284305e4b27395a23db7882d670bdb1bcae1James Dong 60737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::stop() { 608674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 60937187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 61020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 61237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 6138f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 61465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 61737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 61837187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 61937187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 62037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6228f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 6238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 6248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 62665b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 62765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 62865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 62965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 63065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 63165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 63265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong LOGD("Duration from tracks range is [%lld, %lld] us", 63365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 6377837c17063a4c50bc856ba59418516fdab731de7James Dong 63837187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 63937187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 640674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong close(mFd); 641674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mFd = -1; 642674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck = NO_INIT; 64337187916a486504acaf83bea30147eb5fbf46ae5James Dong mStarted = false; 64437187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 64537187916a486504acaf83bea30147eb5fbf46ae5James Dong } 64637187916a486504acaf83bea30147eb5fbf46ae5James Dong 64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 6481acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 649c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 6501acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 651c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 6521acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 653c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 6541acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int64_t size = mOffset - mMdatOffset; 6551acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 656c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 6571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 658c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 65920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 660c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong const off64_t moovOffset = mOffset; 6617837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = true; 6627837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 6637837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 6647837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6677837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 6687837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 6697837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 6707837c17063a4c50bc856ba59418516fdab731de7James Dong 6717837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 672c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 6737837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 674674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 6757837c17063a4c50bc856ba59418516fdab731de7James Dong 6767837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 677c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 6787837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 6797837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 6807837c17063a4c50bc856ba59418516fdab731de7James Dong 6817837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 6827837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 6837837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 6847837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 6852dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 6862dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("The mp4 file will not be streamable."); 6877837c17063a4c50bc856ba59418516fdab731de7James Dong } 6887837c17063a4c50bc856ba59418516fdab731de7James Dong 6890c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 691674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong close(mFd); 692674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mFd = -1; 693674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck = NO_INIT; 694a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = false; 69570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 69637187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 69720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 7354650ff0e86f9e815e3152a806a06c700418d071dJames Dongvoid MPEG4Writer::writeFtypBox(const MetaData *param) { 736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 741b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 742b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 743b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); 747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 75270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 75370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 75470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 75570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 75670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 75770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 75870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 75970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 76070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 76170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 76213aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 76313aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 76413aec890216948b0c364f8f92792129d0335f506James Dong return OK; 76513aec890216948b0c364f8f92792129d0335f506James Dong} 76613aec890216948b0c364f8f92792129d0335f506James Dong 76713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 76813aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 76913aec890216948b0c364f8f92792129d0335f506James Dong} 77013aec890216948b0c364f8f92792129d0335f506James Dong 77113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 77213aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 77313aec890216948b0c364f8f92792129d0335f506James Dong} 77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 775c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 776c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 778c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 779c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 780c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 78803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 78903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 79003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 79103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 79203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 79303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 79403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 79503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 79603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 79703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 79803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 79903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 80003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 801c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 802c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 80330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 80430ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 80503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 806b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 807b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 808c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 809b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 810c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 811b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 812c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 813b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 814c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 815c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 816c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 817c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 818c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 819b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 820b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 821b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 822b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong CHECK(length < 65536); 82330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 824b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 825c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 826b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 827c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 828c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 829b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 830b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 83130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 83230ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 83330ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 83430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 8357837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 836674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 8377837c17063a4c50bc856ba59418516fdab731de7James Dong 8387837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 8397837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 840674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong // This happens only when we write the moov box at the end of 841674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong // recording, not for each output video/audio frame we receive. 842c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 8431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 844c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 8457837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 8467837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 8477837c17063a4c50bc856ba59418516fdab731de7James Dong } 848674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 849674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 850674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 8517837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 8527837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 8537837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 8547837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 8557837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 8567837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = false; 8577837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 8587837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 8597837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 8607837c17063a4c50bc856ba59418516fdab731de7James Dong } 8617837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 862674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 8637837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 8647837c17063a4c50bc856ba59418516fdab731de7James Dong } 8657837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 8667837c17063a4c50bc856ba59418516fdab731de7James Dong} 8677837c17063a4c50bc856ba59418516fdab731de7James Dong 86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 8690c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 87020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8717837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 8727837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 87320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 87420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 87520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 87620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 87720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 87820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 8790c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 88020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 881c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 88220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 88320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8847837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 8857837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 8867837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 8877837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 888c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 8897837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 8907837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 891c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 8927837c17063a4c50bc856ba59418516fdab731de7James Dong } 89320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 89420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 89520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 896674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 89720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 89820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 90020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 901674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 90220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 90320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 906674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 911674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 91520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 916674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 91720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 9200c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 921674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 92320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 92420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 925674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 92620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 92878a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 92978a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 93078a1a286f736888ae7af8860b2c424af0d978848James Dong} 93178a1a286f736888ae7af8860b2c424af0d978848James Dong 932d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 933d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 934d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 935d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 936d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 937d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 938956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 939d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 940d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 941d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 942d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 9431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 944acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 945acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 946acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 947acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 948d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 949d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 950d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 951d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 952d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 953d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 954d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 955d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 956d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 957d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 958d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 959d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 960d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 961d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 962d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 963d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 964d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 96525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 96625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 96725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 96825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 96925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 97025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 97125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 97225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 97325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 97425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 97525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 97625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 97725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 978f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 979f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("setStartTimestampUs: %lld", timeUs); 980f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong CHECK(timeUs >= 0); 9813c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 982065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 983f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 984f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("Earliest track starting time: %lld", mStartTimestampUs); 9853c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 9863c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 9873c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 988f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 9893c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 9903c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 9913c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 9923c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 99358ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 99458ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 99558ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 99658ae9c530247668f8af36e30d228c716c226b3d4James Dong} 99758ae9c530247668f8af36e30d228c716c226b3d4James Dong 99820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 99920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 100020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1001bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 100220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 100325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 100420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 100520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1006a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1007a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1008eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1009bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1010c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1011956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1012be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 101320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 101425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1015548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 101613f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 101713f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 101819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 10198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 10201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 10211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 10221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 10231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 10241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 10251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 10261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1027c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1028c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1029c059860c73678a202bfa33062723e8f82fb779d9James Dong 10301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 10311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 10321f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset() 10331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ? mNumStcoTableEntries * 4 10341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong : mNumStcoTableEntries * 8; 10351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 10361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4); 10371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 103878a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 103978a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 104078a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 104178a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 104278a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 + // stsc box size 104378a1a286f736888ae7af8860b2c424af0d978848James Dong mNumStssTableEntries * 4 + // stss box size 104478a1a286f736888ae7af8860b2c424af0d978848James Dong mNumSttsTableEntries * 8 + // stts box size 104578a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 104678a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 104778a1a286f736888ae7af8860b2c424af0d978848James Dong } 10481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 10491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 10501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 10511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 10521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 10531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong StscTableEntry stscEntry(chunkId, sampleId, 1); 10541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mStscTableEntries.push_back(stscEntry); 10551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStscTableEntries; 10561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 10571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 10581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 10591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mStssTableEntries.push_back(sampleId); 10601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStssTableEntries; 10611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 10621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 10631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 10641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t sampleCount, int64_t durationUs) { 10651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 10661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong SttsTableEntry sttsEntry(sampleCount, durationUs); 10671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mSttsTableEntries.push_back(sttsEntry); 10681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumSttsTableEntries; 10691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 10701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1071c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 10721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStcoTableEntries; 10731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mChunkOffsets.push_back(offset); 10741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 10751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1076c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 1077c059860c73678a202bfa33062723e8f82fb779d9James Dong LOGV("setTimeScale"); 1078c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1079c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1080c059860c73678a202bfa33062723e8f82fb779d9James Dong 1081c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1082c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1083c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1084c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1085c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1086c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1087c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1088c059860c73678a202bfa33062723e8f82fb779d9James Dong 1089c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1090c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1091c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1092c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1093c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1094c059860c73678a202bfa33062723e8f82fb779d9James Dong 10958f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 109619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 109719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 109819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 109919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 110019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 110119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 110219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 110319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 110419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 110519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 110619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 110719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 110819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 110919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 111019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 111119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 111219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 111319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 111419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 111519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 111619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 111719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 111819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 111919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 112019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 112119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 112219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 112319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 112419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 112519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 112619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 112720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 112920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 113020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 113120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 113220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 113420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 113520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 113620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 113720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 113893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 113993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("initTrackingProgressStatus"); 114093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 114193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 114293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 114393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 114493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 114593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 114693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Receive request to track progress status for every %lld us", timeUs); 114793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 114893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 114993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 115093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 115193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 115293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 11531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 11541c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 11551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("ThreadWrapper: %p", me); 11561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 11571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 11581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 11591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 11601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11611c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 11621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("bufferChunk: %p", chunk.mTrack); 11631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 11641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 11651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 11671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 11681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 11701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 11711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 11721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 11731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 11741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 11751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK("Received a chunk for a unknown track" == 0); 11771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 11781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1179fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1180fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong LOGV("writeChunkToFile: %lld from %s track", 1181fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk.mTimestampUs, chunk.mTrack->isAudio()? "audio": "video"); 1182fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1183fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1184fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1185fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1186fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1187fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong off64_t offset = chunk->mTrack->isAvc() 1188fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong ? addLengthPrefixedSample_l(*it) 1189fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1190fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1191fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1192fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1193fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 11941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 11951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 11971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1198fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 11991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1200fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 12011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 12021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1203fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 1204fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong LOGV("writeAllChunks"); 12051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 120670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 120770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 120870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 12091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 121070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 121170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 121270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 12131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 12141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGD("%d chunks are written in the last batch", outstandingChunks); 12151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 12161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1217fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 1218fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong LOGV("findChunkToWrite"); 12191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 12201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 12211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 12221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 12231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 12241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 12251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 12261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 12271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 12281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 12291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 12301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 12311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 12321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 12331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 12341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("Nothing to be written after all"); 1235fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 12361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 12371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 12381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 12391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 12401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1241fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 12421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 12431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 12441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1245fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1246fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1247fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 124870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 124970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 125070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 125170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 125270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 125370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 125470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1255fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 12561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 12571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1258fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1259fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 12601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 12611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 12621c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 12631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("threadFunc"); 12641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1265a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1266fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1267fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 12681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1269fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1270fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1271fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1272fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 12731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 12741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 12751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1276fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong // Actual write without holding the lock in order to 1277fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong // reduce the blocking time for media track threads. 1278fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 1279fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong mLock.unlock(); 1280fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 1281fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong mLock.lock(); 1282fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 12831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1284fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1285fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 12861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 12871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 12881c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 12891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("startWriterThread"); 12901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 12911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 12921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1293e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 12941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 12951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 12961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 12971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 129870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 129970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 13001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 13011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 13021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 13031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 13041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 13051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 13061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 13071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 13081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 13091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 13101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 13111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 131293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1313a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1314a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1315a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1316a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1317a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 131825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 131993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 132019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 132119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 132219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 132370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 132419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 132513f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 132613f6284305e4b27395a23db7882d670bdb1bcae1James Dong if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 132713f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 132813f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 132913f6284305e4b27395a23db7882d670bdb1bcae1James Dong 13305b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong mIsRealTimeRecording = true; 1331e259531ce59ab1f31de5a23124b22536f6a5a767James Dong { 1332e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int32_t isNotRealTime; 1333e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) { 1334e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mIsRealTimeRecording = (isNotRealTime == 0); 1335e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1336e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1337e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 133893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 133993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1340f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1341a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (mIsRealTimeRecording && mOwner->numTracks() > 1) { 1342a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 1343a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 1344a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 1345a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 1346a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 1347a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 1348a472613aec322e25891abf5c77bf3f7e3c244920James Dong * Ideally, this platform-specific value should be defined 1349a472613aec322e25891abf5c77bf3f7e3c244920James Dong * in media_profiles.xml file 1350a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 135170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeUs += kInitialDelayTimeUs; 1352a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 1353a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1354f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1355a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1356f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 135725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 135825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 135925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 136025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1367eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 1368c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 136925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1370956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 13711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStcoTableEntries = 0; 13721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStssTableEntries = 0; 13731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStscTableEntries = 0; 13741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumSttsTableEntries = 0; 13751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 1376872a481558350634a3fd5cb67939de288af00ecbJames Dong mIsMediaTimeAdjustmentOn = false; 1377872a481558350634a3fd5cb67939de288af00ecbJames Dong mPrevMediaTimeAdjustTimestampUs = 0; 1378872a481558350634a3fd5cb67939de288af00ecbJames Dong mMediaTimeAdjustNumFrames = 0; 1379872a481558350634a3fd5cb67939de288af00ecbJames Dong mPrevMediaTimeAdjustSample = 0; 1380872a481558350634a3fd5cb67939de288af00ecbJames Dong mTotalDriftTimeToAdjustUs = 0; 1381872a481558350634a3fd5cb67939de288af00ecbJames Dong mPrevTotalAccumDriftTimeUs = 0; 138243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 138425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 138625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 138725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 139037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1391a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 139237187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1393a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1394a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 139537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 1396cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong LOGD("Stopping %s track", mIsAudio? "Audio": "Video"); 1397eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 1398eaae38445a340c4857c1c5569475879a728e63b7James Dong LOGE("Stop() called but track is not started"); 1399eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 1400eaae38445a340c4857c1c5569475879a728e63b7James Dong } 1401eaae38445a340c4857c1c5569475879a728e63b7James Dong 140220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 140337187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 140420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 141037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = (status_t) dummy; 141137187916a486504acaf83bea30147eb5fbf46ae5James Dong 1412cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong LOGD("Stopping %s track source", mIsAudio? "Audio": "Video"); 141337187916a486504acaf83bea30147eb5fbf46ae5James Dong { 141437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = mSource->stop(); 141537187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK && status != ERROR_END_OF_STREAM) { 141637187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 141737187916a486504acaf83bea30147eb5fbf46ae5James Dong } 141837187916a486504acaf83bea30147eb5fbf46ae5James Dong } 141937187916a486504acaf83bea30147eb5fbf46ae5James Dong 1420cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong LOGD("%s track stopped", mIsAudio? "Audio": "Video"); 142137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 142425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 142525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 142625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 142725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 142820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 143120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 143237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 143337187916a486504acaf83bea30147eb5fbf46ae5James Dong return (void *) err; 143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 143520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 14373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("getNalUnitType: %d", byte); 14383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 14403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 14413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 14423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 14443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 14453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("findNextStartCode: %p %d", data, length); 14473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 14493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 14503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 14513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 14523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 14543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 14553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 14573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 14583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 14603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 14613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("parseParamSet"); 14633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 14643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 14653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 14673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 14683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 14693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Param set is malformed, since its length is 0"); 14703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 14713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 14743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 14753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 14763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Seq parameter set malformed"); 14773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 14783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 14803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 14813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 14823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 14833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 14843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 14853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 14863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 14873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Inconsistent profile/level found in seq parameter sets"); 14883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 14893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 14923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 14933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 14943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 14963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 14973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 14993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 15003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("copyAVCCodecSpecificData"); 15013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 15033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 15043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 15053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Codec specific data length too short: %d", size); 15063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 15073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 15103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 15113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 15123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 15133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 15143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 15163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 15173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("parseAVCCodecSpecificData"); 15193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 15203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 15213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 15223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 15233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 15243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 15253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 15263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 15273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 15283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 15293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 15303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 15313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 15323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 15333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 15343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("SPS must come before PPS"); 15353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 15363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 15383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 15393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 15413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 15423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 15433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("SPS must come before PPS"); 15443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 15453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 15473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 15483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 15503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 15513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Only SPS and PPS Nal units are expected"); 15523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 15533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 15563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 15573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 15603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 15613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 15623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 15633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 15663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 15673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 15683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 15693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Cound not find sequence parameter set"); 15703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 15713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 15743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 15753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 15763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 15803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 15813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 15823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 15833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Cound not find picture parameter set"); 15843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 15853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 15873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Too many pic parameter sets (%d) found", nPicParamSets); 15883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 15893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 15933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 15943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 15953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 15963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 15973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 15983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 15993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 16033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 1604548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 160503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 160603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 1607548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 160803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 1609548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Already have codec specific data"); 161003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 161103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 161203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 16133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 16143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Codec specific data length too short: %d", size); 161503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 161603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 161703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 16183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 16193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 16203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 162103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 162203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 16233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 162403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 162503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 162603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 16273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 16283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 162903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 163003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 16313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 16323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 16333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 16343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 163503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 16363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 1637b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 1638b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 1639b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 1640b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 1641b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 164203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 16433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 16443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 16453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 16463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 16473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 16483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 16493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 16503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 16513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 16523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 16533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 16553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 16563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 16573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 16603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 16613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 16623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 16633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 16643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 16653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 16663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 16673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 16683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 16693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 16713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 16723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 16733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 167403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 167503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 167603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 167703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1678872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 1679872a481558350634a3fd5cb67939de288af00ecbJames Dong* The video track's media time adjustment for real-time applications 1680872a481558350634a3fd5cb67939de288af00ecbJames Dong* is described as follows: 1681872a481558350634a3fd5cb67939de288af00ecbJames Dong* 1682872a481558350634a3fd5cb67939de288af00ecbJames Dong* First, the media time adjustment is done for every period of 1683872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs. kVideoMediaTimeAdjustPeriodTimeUs 1684872a481558350634a3fd5cb67939de288af00ecbJames Dong* is currently a fixed value chosen heuristically. The value of 1685872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs should not be very large or very small 1686872a481558350634a3fd5cb67939de288af00ecbJames Dong* for two considerations: on one hand, a relatively large value 1687872a481558350634a3fd5cb67939de288af00ecbJames Dong* helps reduce large fluctuation of drift time in the audio encoding 1688872a481558350634a3fd5cb67939de288af00ecbJames Dong* path; while on the other hand, a relatively small value helps keep 1689872a481558350634a3fd5cb67939de288af00ecbJames Dong* restoring synchronization in audio/video more frequently. Note for the 1690872a481558350634a3fd5cb67939de288af00ecbJames Dong* very first period of kVideoMediaTimeAdjustPeriodTimeUs, there is 1691872a481558350634a3fd5cb67939de288af00ecbJames Dong* no media time adjustment for the video track. 1692872a481558350634a3fd5cb67939de288af00ecbJames Dong* 1693872a481558350634a3fd5cb67939de288af00ecbJames Dong* Second, the total accumulated audio track time drift found 1694872a481558350634a3fd5cb67939de288af00ecbJames Dong* in a period of kVideoMediaTimeAdjustPeriodTimeUs is distributed 1695872a481558350634a3fd5cb67939de288af00ecbJames Dong* over a stream of incoming video frames. The number of video frames 1696872a481558350634a3fd5cb67939de288af00ecbJames Dong* affected is determined based on the number of recorded video frames 1697872a481558350634a3fd5cb67939de288af00ecbJames Dong* within the past kVideoMediaTimeAdjustPeriodTimeUs period. 1698872a481558350634a3fd5cb67939de288af00ecbJames Dong* We choose to distribute the drift time over only a portion 1699872a481558350634a3fd5cb67939de288af00ecbJames Dong* (rather than all) of the total number of recorded video frames 1700872a481558350634a3fd5cb67939de288af00ecbJames Dong* in order to make sure that the video track media time adjustment is 1701872a481558350634a3fd5cb67939de288af00ecbJames Dong* completed for the current period before the next video track media 1702872a481558350634a3fd5cb67939de288af00ecbJames Dong* time adjustment period starts. Currently, the portion chosen is a 1703872a481558350634a3fd5cb67939de288af00ecbJames Dong* half (0.5). 1704872a481558350634a3fd5cb67939de288af00ecbJames Dong* 1705872a481558350634a3fd5cb67939de288af00ecbJames Dong* Last, various additional checks are performed to ensure that 1706872a481558350634a3fd5cb67939de288af00ecbJames Dong* the actual audio encoding path does not have too much drift. 1707872a481558350634a3fd5cb67939de288af00ecbJames Dong* In particular, 1) we want to limit the average incremental time 1708872a481558350634a3fd5cb67939de288af00ecbJames Dong* adjustment for each video frame to be less than a threshold 1709872a481558350634a3fd5cb67939de288af00ecbJames Dong* for a single period of kVideoMediaTimeAdjustPeriodTimeUs. 1710872a481558350634a3fd5cb67939de288af00ecbJames Dong* Currently, the threshold is set to 5 ms. If the average incremental 1711872a481558350634a3fd5cb67939de288af00ecbJames Dong* media time adjustment for a video frame is larger than the 1712872a481558350634a3fd5cb67939de288af00ecbJames Dong* threshold, the audio encoding path has too much time drift. 1713872a481558350634a3fd5cb67939de288af00ecbJames Dong* 2) We also want to limit the total time drift in the audio 1714872a481558350634a3fd5cb67939de288af00ecbJames Dong* encoding path to be less than a threshold for a period of 1715872a481558350634a3fd5cb67939de288af00ecbJames Dong* kVideoMediaTimeAdjustPeriodTimeUs. Currently, the threshold 1716872a481558350634a3fd5cb67939de288af00ecbJames Dong* is 0.5% of kVideoMediaTimeAdjustPeriodTimeUs. If the time drift of 1717872a481558350634a3fd5cb67939de288af00ecbJames Dong* the audio encoding path is larger than the threshold, the audio 1718872a481558350634a3fd5cb67939de288af00ecbJames Dong* encoding path has too much time drift. We treat the large time 1719872a481558350634a3fd5cb67939de288af00ecbJames Dong* drift of the audio encoding path as errors, since there is no 1720872a481558350634a3fd5cb67939de288af00ecbJames Dong* way to keep audio/video in synchronization for real-time 1721872a481558350634a3fd5cb67939de288af00ecbJames Dong* applications if the time drift is too large unless we drop some 1722872a481558350634a3fd5cb67939de288af00ecbJames Dong* video frames, which has its own problems that we don't want 1723872a481558350634a3fd5cb67939de288af00ecbJames Dong* to get into for the time being. 1724872a481558350634a3fd5cb67939de288af00ecbJames Dong*/ 1725872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::adjustMediaTime(int64_t *timestampUs) { 1726872a481558350634a3fd5cb67939de288af00ecbJames Dong if (*timestampUs - mPrevMediaTimeAdjustTimestampUs >= 1727872a481558350634a3fd5cb67939de288af00ecbJames Dong kVideoMediaTimeAdjustPeriodTimeUs) { 1728872a481558350634a3fd5cb67939de288af00ecbJames Dong 1729872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGV("New media time adjustment period at %lld us", *timestampUs); 1730872a481558350634a3fd5cb67939de288af00ecbJames Dong mIsMediaTimeAdjustmentOn = true; 1731872a481558350634a3fd5cb67939de288af00ecbJames Dong mMediaTimeAdjustNumFrames = 1732872a481558350634a3fd5cb67939de288af00ecbJames Dong (mNumSamples - mPrevMediaTimeAdjustSample) >> 1; 1733872a481558350634a3fd5cb67939de288af00ecbJames Dong 1734872a481558350634a3fd5cb67939de288af00ecbJames Dong mPrevMediaTimeAdjustTimestampUs = *timestampUs; 1735872a481558350634a3fd5cb67939de288af00ecbJames Dong mPrevMediaTimeAdjustSample = mNumSamples; 1736872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t totalAccumDriftTimeUs = mOwner->getDriftTimeUs(); 1737872a481558350634a3fd5cb67939de288af00ecbJames Dong mTotalDriftTimeToAdjustUs = 1738872a481558350634a3fd5cb67939de288af00ecbJames Dong totalAccumDriftTimeUs - mPrevTotalAccumDriftTimeUs; 1739872a481558350634a3fd5cb67939de288af00ecbJames Dong 1740872a481558350634a3fd5cb67939de288af00ecbJames Dong mPrevTotalAccumDriftTimeUs = totalAccumDriftTimeUs; 1741872a481558350634a3fd5cb67939de288af00ecbJames Dong 1742872a481558350634a3fd5cb67939de288af00ecbJames Dong // Check on incremental adjusted time per frame 1743872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t adjustTimePerFrameUs = 1744872a481558350634a3fd5cb67939de288af00ecbJames Dong mTotalDriftTimeToAdjustUs / mMediaTimeAdjustNumFrames; 1745872a481558350634a3fd5cb67939de288af00ecbJames Dong 1746872a481558350634a3fd5cb67939de288af00ecbJames Dong if (adjustTimePerFrameUs < 0) { 1747872a481558350634a3fd5cb67939de288af00ecbJames Dong adjustTimePerFrameUs = -adjustTimePerFrameUs; 1748872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1749872a481558350634a3fd5cb67939de288af00ecbJames Dong if (adjustTimePerFrameUs >= 5000) { 1750872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGE("Adjusted time per video frame is %lld us", 1751872a481558350634a3fd5cb67939de288af00ecbJames Dong adjustTimePerFrameUs); 1752872a481558350634a3fd5cb67939de288af00ecbJames Dong CHECK(!"Video frame time adjustment is too large!"); 1753872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1754872a481558350634a3fd5cb67939de288af00ecbJames Dong 1755872a481558350634a3fd5cb67939de288af00ecbJames Dong // Check on total accumulated time drift within a period of 1756872a481558350634a3fd5cb67939de288af00ecbJames Dong // kVideoMediaTimeAdjustPeriodTimeUs. 1757872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftPercentage = (mTotalDriftTimeToAdjustUs * 1000) 1758872a481558350634a3fd5cb67939de288af00ecbJames Dong / kVideoMediaTimeAdjustPeriodTimeUs; 1759872a481558350634a3fd5cb67939de288af00ecbJames Dong 1760872a481558350634a3fd5cb67939de288af00ecbJames Dong if (driftPercentage < 0) { 1761872a481558350634a3fd5cb67939de288af00ecbJames Dong driftPercentage = -driftPercentage; 1762872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1763872a481558350634a3fd5cb67939de288af00ecbJames Dong if (driftPercentage > 5) { 1764872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGE("Audio track has time drift %lld us over %lld us", 1765872a481558350634a3fd5cb67939de288af00ecbJames Dong mTotalDriftTimeToAdjustUs, 1766872a481558350634a3fd5cb67939de288af00ecbJames Dong kVideoMediaTimeAdjustPeriodTimeUs); 1767872a481558350634a3fd5cb67939de288af00ecbJames Dong 1768872a481558350634a3fd5cb67939de288af00ecbJames Dong CHECK(!"The audio track media time drifts too much!"); 1769872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1770872a481558350634a3fd5cb67939de288af00ecbJames Dong 1771872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1772872a481558350634a3fd5cb67939de288af00ecbJames Dong 1773872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsMediaTimeAdjustmentOn) { 1774872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mNumSamples - mPrevMediaTimeAdjustSample <= 1775872a481558350634a3fd5cb67939de288af00ecbJames Dong mMediaTimeAdjustNumFrames) { 1776872a481558350634a3fd5cb67939de288af00ecbJames Dong 1777872a481558350634a3fd5cb67939de288af00ecbJames Dong // Do media time incremental adjustment 1778872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t incrementalAdjustTimeUs = 1779872a481558350634a3fd5cb67939de288af00ecbJames Dong (mTotalDriftTimeToAdjustUs * 1780872a481558350634a3fd5cb67939de288af00ecbJames Dong (mNumSamples - mPrevMediaTimeAdjustSample)) 1781872a481558350634a3fd5cb67939de288af00ecbJames Dong / mMediaTimeAdjustNumFrames; 1782872a481558350634a3fd5cb67939de288af00ecbJames Dong 1783872a481558350634a3fd5cb67939de288af00ecbJames Dong *timestampUs += 1784872a481558350634a3fd5cb67939de288af00ecbJames Dong (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs); 1785872a481558350634a3fd5cb67939de288af00ecbJames Dong 1786872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGV("Incremental video frame media time adjustment: %lld us", 1787872a481558350634a3fd5cb67939de288af00ecbJames Dong (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs)); 1788872a481558350634a3fd5cb67939de288af00ecbJames Dong } else { 1789872a481558350634a3fd5cb67939de288af00ecbJames Dong // Within the remaining adjustment period, 1790872a481558350634a3fd5cb67939de288af00ecbJames Dong // no incremental adjustment is needed. 1791872a481558350634a3fd5cb67939de288af00ecbJames Dong *timestampUs += 1792872a481558350634a3fd5cb67939de288af00ecbJames Dong (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs); 1793872a481558350634a3fd5cb67939de288af00ecbJames Dong 1794872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGV("Fixed video frame media time adjustment: %lld us", 1795872a481558350634a3fd5cb67939de288af00ecbJames Dong (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs)); 1796872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1797872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1798872a481558350634a3fd5cb67939de288af00ecbJames Dong} 1799872a481558350634a3fd5cb67939de288af00ecbJames Dong 1800872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 1801872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 1802872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 1803872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 1804872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 1805872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 1806872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 1807872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 1808872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 1809872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 1810872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 1811872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 1812872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 1813872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 1814872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1815872a481558350634a3fd5cb67939de288af00ecbJames Dong} 1816872a481558350634a3fd5cb67939de288af00ecbJames Dong 181737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 181830ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 181913aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 182043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 182113aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 182213aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 182313aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 18248f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t lastTimestampUs = 0; // Previous sample time stamp in ms 18258f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t lastDurationUs = 0; // Between the previous two samples in ms 1826c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t currDurationTicks = 0; // Timescale based ticks 1827c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t lastDurationTicks = 0; // Timescale based ticks 18288f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 1829be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 1830a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 18311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t timestampUs; 1832e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1833a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 1834a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 1835a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } else { 1836a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 1837a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 1838985f838934510983d8a887461e98dca60a6e858fJames Dong setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO); 1839985f838934510983d8a887461e98dca60a6e858fJames Dong 1840d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 184120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1842ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mNumSamples = 0; 184393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 184420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 184593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 184620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 184720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 184913aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 185120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 185220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1853a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 1854a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 1855a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 1856a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 1857a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 1858a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 1859a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 1860a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1861a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 186230ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 186330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 186403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 186503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 186603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 1867548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 1868548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 18691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 187003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 187103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 187203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 187303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 1874be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 18751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 187603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 187703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 187803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 187903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 188003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 188103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 188230ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 188330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 188430ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 188530ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 188630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1887548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 188830ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 1889a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1890a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1891d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 1892d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 1893d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 1894d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 1895d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 1896d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 1897d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 1898d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 1899d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 1900d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 19011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 1902e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 1903b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 1904b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mIsAvc) { 1905b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 1906b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 1907b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 1908b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 1909b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 1910b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 1911050b28a593350047845a45a14cc5026221ac1620James Dong 1912d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 19131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 19141f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 19151f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1916d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 1917d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 1918d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1919d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1920d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 1921d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 1922d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1923d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1924d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1925050b28a593350047845a45a14cc5026221ac1620James Dong 1926d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 1927d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 1928d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 19298428af5381e835cc783b7ecb0d71cb60961c99c2James Dong /* 19308428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * The original timestamp found in the data buffer will be modified as below: 19318428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * 19328428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * There is a playback offset into this track if the track's start time 19338428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * is not the same as the movie start time, which will be recorded in edst 19348428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * box of the output file. The playback offset is to make sure that the 19358428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * starting time of the audio/video tracks are synchronized. Although the 19368428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * track's media timestamp may be subject to various modifications 19378428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * as outlined below, the track's playback offset time remains unchanged 19388428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * once the first data buffer of the track is received. 19398428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * 19408428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * The media time stamp will be calculated by subtracting the playback offset 19418428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * (and potential pause durations) from the original timestamp in the buffer. 19428428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * 19438428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * If this track is a video track for a real-time recording application with 19448428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * both audio and video tracks, its media timestamp will subject to further 19458428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * modification based on the media clock of the audio track. This modification 19468428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * is needed for the purpose of maintaining good audio/video synchronization. 19478428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * 19488428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * If the recording session is paused and resumed multiple times, the track 19498428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * media timestamp will be modified as if the recording session had never been 19508428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * paused at all during playback of the recorded output file. In other words, 19518428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * the output file will have no memory of pause/resume durations. 19528428af5381e835cc783b7ecb0d71cb60961c99c2James Dong * 19538428af5381e835cc783b7ecb0d71cb60961c99c2James Dong */ 1954d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 19558428af5381e835cc783b7ecb0d71cb60961c99c2James Dong LOGV("%s timestampUs: %lld", mIsAudio? "Audio": "Video", timestampUs); 1956d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1957d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 195870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mNumSamples == 0) { 195970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 1960f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 1961f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 19628428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 19633c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 196448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 1965a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 19668428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 19678428af5381e835cc783b7ecb0d71cb60961c99c2James Dong CHECK(durExcludingEarlierPausesUs >= 0); 19688428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 19698428af5381e835cc783b7ecb0d71cb60961c99c2James Dong CHECK(pausedDurationUs >= lastDurationUs); 19708428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 1971a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 1972a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1973a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1974a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 19758428af5381e835cc783b7ecb0d71cb60961c99c2James Dong CHECK(timestampUs >= 0); 1976872a481558350634a3fd5cb67939de288af00ecbJames Dong 1977872a481558350634a3fd5cb67939de288af00ecbJames Dong // Media time adjustment for real-time applications 1978872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsRealTimeRecording) { 1979872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 1980872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 1981872a481558350634a3fd5cb67939de288af00ecbJames Dong } else { 1982872a481558350634a3fd5cb67939de288af00ecbJames Dong adjustMediaTime(×tampUs); 1983e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1984e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1985872a481558350634a3fd5cb67939de288af00ecbJames Dong 1986e259531ce59ab1f31de5a23124b22536f6a5a767James Dong CHECK(timestampUs >= 0); 1987e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (mNumSamples > 1) { 1988e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (timestampUs <= lastTimestampUs) { 19894f86a980fee1880dca61b828599fa6d76755a485James Dong LOGW("Frame arrives too late!"); 19904f86a980fee1880dca61b828599fa6d76755a485James Dong // Don't drop the late frame, since dropping a frame may cause 19914f86a980fee1880dca61b828599fa6d76755a485James Dong // problems later during playback 19924f86a980fee1880dca61b828599fa6d76755a485James Dong 19934f86a980fee1880dca61b828599fa6d76755a485James Dong // The idea here is to avoid having two or more samples with the 19944f86a980fee1880dca61b828599fa6d76755a485James Dong // same timestamp in the output file. 19954f86a980fee1880dca61b828599fa6d76755a485James Dong if (mTimeScale >= 1000000LL) { 199640e9940fadf22daa64c1e766fa8a855c7b149c17James Dong timestampUs = lastTimestampUs + 1; 19974f86a980fee1880dca61b828599fa6d76755a485James Dong } else { 199840e9940fadf22daa64c1e766fa8a855c7b149c17James Dong timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale; 19994f86a980fee1880dca61b828599fa6d76755a485James Dong } 2000e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2001e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 2002e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 20038428af5381e835cc783b7ecb0d71cb60961c99c2James Dong LOGV("%s media time stamp: %lld and previous paused duration %lld", 20048428af5381e835cc783b7ecb0d71cb60961c99c2James Dong mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs); 2005c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 2006c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 20073b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 20083b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 20098644c14618d30d9e57a69df40ed939986ebf02c4James Dong mSampleSizes.push_back(sampleSize); 2010ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong ++mNumSamples; 2011ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples > 2) { 2012c059860c73678a202bfa33062723e8f82fb779d9James Dong // We need to use the time scale based ticks, rather than the 2013c059860c73678a202bfa33062723e8f82fb779d9James Dong // timestamp itself to determine whether we have to use a new 2014c059860c73678a202bfa33062723e8f82fb779d9James Dong // stts entry, since we may have rounding errors. 2015c059860c73678a202bfa33062723e8f82fb779d9James Dong // The calculation is intended to reduce the accumulated 2016c059860c73678a202bfa33062723e8f82fb779d9James Dong // rounding errors. 2017c059860c73678a202bfa33062723e8f82fb779d9James Dong currDurationTicks = 2018c059860c73678a202bfa33062723e8f82fb779d9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 2019c059860c73678a202bfa33062723e8f82fb779d9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2020c059860c73678a202bfa33062723e8f82fb779d9James Dong 2021a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2022a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2023a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (mNumSamples == 3 || currDurationTicks != lastDurationTicks) { 2024a472613aec322e25891abf5c77bf3f7e3c244920James Dong LOGV("%s lastDurationUs: %lld us, currDurationTicks: %lld us", 2025a472613aec322e25891abf5c77bf3f7e3c244920James Dong mIsAudio? "Audio": "Video", lastDurationUs, currDurationTicks); 20261f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneSttsTableEntry(sampleCount, lastDurationUs); 2027be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2028be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2029be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2030be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2031be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2032be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2033ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples >= 2 && previousSampleSize != sampleSize) { 2034be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2035be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 20368644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2037be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2038a472613aec322e25891abf5c77bf3f7e3c244920James Dong LOGV("%s timestampUs/lastTimestampUs: %lld/%lld", 2039a472613aec322e25891abf5c77bf3f7e3c244920James Dong mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs); 20408644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2041c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 20428644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 204320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2044d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 20451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStssTableEntry(mNumSamples); 2046d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2047d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 204893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 204993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 205093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 205193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2052faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 205393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 205443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2055c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 205658ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 205758ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mChunkOffsets.empty()) { 20581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 205958ae9c530247668f8af36e30d228c716c226b3d4James Dong } 206058ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 206158ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 206258ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 206358ae9c530247668f8af36e30d228c716c226b3d4James Dong } 206413aec890216948b0c364f8f92792129d0335f506James Dong 206513aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 206613aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 20671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 20681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 206913aec890216948b0c364f8f92792129d0335f506James Dong } else { 207013aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 207113aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 207213aec890216948b0c364f8f92792129d0335f506James Dong } else { 207343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 207443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 207543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 207643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 207743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 207813aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 207913aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 208013aec890216948b0c364f8f92792129d0335f506James Dong (--(mStscTableEntries.end()))->samplesPerChunk != 208113aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size()) { 20821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(nChunks, mChunkSamples.size()); 208313aec890216948b0c364f8f92792129d0335f506James Dong } 20841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 208513aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 208613aec890216948b0c364f8f92792129d0335f506James Dong } 208713aec890216948b0c364f8f92792129d0335f506James Dong } 208813aec890216948b0c364f8f92792129d0335f506James Dong } 208913aec890216948b0c364f8f92792129d0335f506James Dong 209020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 209125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 2092a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong if (mSampleSizes.empty() || // no samples written 2093a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong (!mIsAudio && mNumStssTableEntries == 0) || // no sync frames for video 2094a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong (OK != checkCodecSpecificData())) { // no codec specific data 2095690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2096f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 2097bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2098be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 209913aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 210043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 21011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(1, mNumSamples); 210258ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 21031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 21041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 210513aec890216948b0c364f8f92792129d0335f506James Dong } 210613aec890216948b0c364f8f92792129d0335f506James Dong 2107be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2108be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2109be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2110ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples == 1) { 21118f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 2112be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2113be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2114be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2115a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2116a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (mNumSamples <= 2) { 2117a472613aec322e25891abf5c77bf3f7e3c244920James Dong addOneSttsTableEntry(1, lastDurationUs); 2118a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 2119a472613aec322e25891abf5c77bf3f7e3c244920James Dong addOneSttsTableEntry(sampleCount - 1, lastDurationUs); 2120a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2121a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 2122a472613aec322e25891abf5c77bf3f7e3c244920James Dong addOneSttsTableEntry(sampleCount, lastDurationUs); 2123a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2124a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2125c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 212625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 212743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 212843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 212943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 21301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 21311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video"); 2132872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2133872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs()); 2134872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2135365a963142093a1cd8efdcea76b5f65096a5b115James Dong 213637187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 213737187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 213837187916a486504acaf83bea30147eb5fbf46ae5James Dong } 213937187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2140365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2141365a963142093a1cd8efdcea76b5f65096a5b115James Dong 214243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 214343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 214443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 214543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 214643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 214743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mIsAudio? 0: 1); 214843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 214943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 215043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 215143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 215243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 215343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 215443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 215543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mNumSamples); 215643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 215770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong // The system delay time excluding the requested initial delay that 215870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong // is used to eliminate the recording sound. 215970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t initialDelayUs = 216070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - kInitialDelayTimeUs; 216170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 216270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 216370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 216470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 216543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 216643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 216743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 216843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 216970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 217070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 217170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 217270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 217370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 217470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 217570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 217670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 217743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 217843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 217943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2180faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 2181faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong LOGV("trackProgressStatus: %lld us", timeUs); 2182215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 2183215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 218493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Fire time tracking progress status at %lld us", timeUs); 2185bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 218693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 218793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 218893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 218993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2190faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 2191bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 2192faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 2193bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 2194faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2195faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 2196faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 2197faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 2198bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2199bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2200faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2201faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 2202faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2203faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2204faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 2205faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 2206bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2207bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2208faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2209faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 2210faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 2211bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2212bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2213faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 2214faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2215faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 2216faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2217d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 2218d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong LOGV("setDriftTimeUs: %lld us", driftTimeUs); 2219e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2220d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 2221e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2222e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2223e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 2224e259531ce59ab1f31de5a23124b22536f6a5a767James Dong LOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 2225e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2226e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 2227e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2228e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2229b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 2230b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 2231b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 2232b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 22331c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 22341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("bufferChunk"); 22351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 22361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 22371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 223813aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 223920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 224020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22413b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 2242c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 224320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 224420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2245d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2246d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 2247d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 2248d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2249690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 2250690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 2251690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2252690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2253690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2254690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2255690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2256690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 2257a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong LOGE("Missing codec specific data"); 2258690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2259690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2260690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2261690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2262690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 2263a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong LOGE("Unexepected codec specific data found"); 2264690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2265690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2266690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2267690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2268690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2269690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2270b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 227120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("%s track time scale: %d", 22731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 22748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 227520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 2276b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 2277b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 2278b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 2279b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 2280b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 2281b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 2282b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2283b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 2284b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2285b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 2286b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2287b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 2288b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 2289b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 2290b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 2291b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 2292b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2293b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2294b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2295b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 2296b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 2297b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2298b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 2299b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2300b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 2301b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2302b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 2303b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2304b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 2305b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 2306b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mIsAudio) { 2307b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 2308b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2309b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 2310b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 2311b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 2312b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 2313b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2314b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2315b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 2316b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2318b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2319b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2320b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mp4v"); 2321b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2322b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("s263"); 2323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2324b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avc1"); 2325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong LOGE("Unknown mime type '%s'.", mime); 2327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 2333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 2341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 2345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 2346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 2347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 2348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 2350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(" ", 32); 2351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 2352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 2353b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(23 + mCodecSpecificDataSize < 128); 2355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 2358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 2360b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 2362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2363b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 2365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 2366b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2367b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 2369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2372b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *fourcc = NULL; 2373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "samr"; 2375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "sawb"; 2377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "mp4a"; 2379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong LOGE("Unknown mime type '%s'.", mime); 2381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 2385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 2388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 2391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 2393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 2394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 2398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 2399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 2401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 2403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 2406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 2411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2412b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 2413b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificDataSize > 0); 2414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 2416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificDataSize + 23 < 128); 2417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 2422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 2423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 2428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2429b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 2430b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2431b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // max bit rate 2432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // avg bit rate 2433b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2434b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2435b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2436b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2437b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2438b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2439b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2441b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2442b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2443b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2444b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2445b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2446b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2447b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 2449b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 2450b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificDataSize > 0); 2451b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2452b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2453b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2454b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2455b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2456b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2457b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 2458b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 2459b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2460b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2461b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2462b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2463b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 2464b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2465b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 2466b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 0x77, 0x00, 2467b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00, 2468b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00 2469b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2470b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 2471b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2472b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2473b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2474b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2475b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2476b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2477b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2478b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2479b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2482b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2483b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2487b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTkhdBox(time_t now) { 2488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 2489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 2490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 2491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 2492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2494b5212db69734962f55e1493d3e696794172ced51James Dong mOwner->writeInt32(mTrackId + 1); // track id starts with 1 2495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 24968f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 2497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 2498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 2499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2501b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2502b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2503b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 2504b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 2505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2507b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 250920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 2516b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2517b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 2523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 2526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 2527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 2528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 2529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 2530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 2536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 2537b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 2539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2542b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 2544b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 2545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2546b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 2547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 2552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2556b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMdhdBox(time_t now) { 2557b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 2558b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 2559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2561b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 2563b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 2564b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 2565b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 2566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 2567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 2568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 2569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 2570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // language code 2571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 2576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 2577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 2578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 2579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 2581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 2582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 2583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 2587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 2588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 2589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 2590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2591b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 2592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 2595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 2596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 2598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 2599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 2600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 2603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 2604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 2605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 2606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 2609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 2610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificDataSize >= 5); 2611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 2613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 2614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 2615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 2616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 2617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2618b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 2619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 2622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 2623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 2624b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 2626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 2627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 2628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 2631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 2632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 2633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 2634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 2635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 2636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 2639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stts"); 2640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mNumSttsTableEntries); 264270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 2643a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Compensate for small start time difference from different media tracks 2644a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 2645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mStartTimestampUs > moovStartTimeUs); 2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t prevTimestampUs = trackStartTimeOffsetUs; 2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 2652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mSttsTableEntries.end(); ++it) { 2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(it->sampleCount); 2654a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure that we are calculating the sample duration the exactly 2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // same way as we made decision on how to create stts entries. 2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs; 2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL - 2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong prevTimestampUs += (it->sampleCount * it->sampleDurationUs); 266120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(dur); 2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 266620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 2668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mNumStssTableEntries); // number of sync frames 2671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<int32_t>::iterator it = mStssTableEntries.begin(); 2672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mStssTableEntries.end(); ++it) { 2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(*it); 2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 2676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 267725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 2678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mSamplesHaveSameSize) { 2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong List<size_t>::iterator it = mSampleSizes.begin(); 2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(*it); // default sample size 2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mNumSamples); 2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mSamplesHaveSameSize) { 2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<size_t>::iterator it = mSampleSizes.begin(); 2690b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mSampleSizes.end(); ++it) { 2691b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(*it); 2692b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 269620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 2698b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 2699b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2700b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mNumStscTableEntries); 2701b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 2702b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mStscTableEntries.end(); ++it) { 2703b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(it->firstChunk); 2704b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(it->samplesPerChunk); 2705b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(it->sampleDescriptionId); 2706b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2707b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 2708b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 270920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2710b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 2711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mNumStcoTableEntries); 2714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<off64_t>::iterator it = mChunkOffsets.begin(); 2715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mChunkOffsets.end(); ++it) { 2716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (use32BitOffset) { 2717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(static_cast<int32_t>(*it)); 2718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt64((*it)); 2720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 272320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 272420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 272520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 2726