MPEG4Writer.cpp revision 411ba422e3635d534928ffd81abf54f4f291c739
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> 2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h> 3018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 3103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h> 3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 34d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h> 3507ec01904613a0bac32caaa8444b4690998faed7James Dong#include <cutils/properties.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 5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 52bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId); 538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 5737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t stop(); 5837187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 5925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 613b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 62d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 63b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTrackHeader(bool use32BitOffset = true); 641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 68c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong void addChunkOffset(off64_t offset); 6970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int32_t getTrackId() const { return mTrackId; } 70dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 75693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 77a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 78a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 79eaae38445a340c4857c1c5569475879a728e63b7James Dong volatile bool mStarted; 801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 83bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t mTrackId; 84c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 8543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t mMaxChunkDurationUs; 86e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 87e259531ce59ab1f31de5a23124b22536f6a5a767James Dong bool mIsRealTimeRecording; 88e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int64_t mMaxTimeStampUs; 89d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // mNumSamples is used to track how many samples in mSampleSizes List. 96ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // This is to reduce the cost associated with mSampleSizes.size() call, 97ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // since it is O(n). Ideally, the fix should be in List class. 98ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong size_t mNumSamples; 998644c14618d30d9e57a69df40ed939986ebf02c4James Dong List<size_t> mSampleSizes; 100be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong bool mSamplesHaveSameSize; 101be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 10213aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 1031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStcoTableEntries; 105c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong List<off64_t> mChunkOffsets; 10613aec890216948b0c364f8f92792129d0335f506James Dong 1071f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStscTableEntries; 10813aec890216948b0c364f8f92792129d0335f506James Dong struct StscTableEntry { 10913aec890216948b0c364f8f92792129d0335f506James Dong 11013aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 11113aec890216948b0c364f8f92792129d0335f506James Dong : firstChunk(chunk), 11213aec890216948b0c364f8f92792129d0335f506James Dong samplesPerChunk(samples), 11313aec890216948b0c364f8f92792129d0335f506James Dong sampleDescriptionId(id) {} 11413aec890216948b0c364f8f92792129d0335f506James Dong 11513aec890216948b0c364f8f92792129d0335f506James Dong uint32_t firstChunk; 11613aec890216948b0c364f8f92792129d0335f506James Dong uint32_t samplesPerChunk; 11713aec890216948b0c364f8f92792129d0335f506James Dong uint32_t sampleDescriptionId; 11813aec890216948b0c364f8f92792129d0335f506James Dong }; 11913aec890216948b0c364f8f92792129d0335f506James Dong List<StscTableEntry> mStscTableEntries; 12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStssTableEntries; 122050b28a593350047845a45a14cc5026221ac1620James Dong List<int32_t> mStssTableEntries; 123050b28a593350047845a45a14cc5026221ac1620James Dong 124be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong struct SttsTableEntry { 125be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 12679761ab096f57c3027fad9556c2bc436672d614eJames Dong SttsTableEntry(uint32_t count, uint32_t duration) 12779761ab096f57c3027fad9556c2bc436672d614eJames Dong : sampleCount(count), sampleDuration(duration) {} 128be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 129be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t sampleCount; 13079761ab096f57c3027fad9556c2bc436672d614eJames Dong uint32_t sampleDuration; // time scale based 131be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong }; 132965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t mNumSttsTableEntries; 133be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SttsTableEntry> mSttsTableEntries; 134be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 135965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong struct CttsTableEntry { 136965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CttsTableEntry(uint32_t count, int32_t timescaledDur) 137965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong : sampleCount(count), sampleDuration(timescaledDur) {} 138965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 139965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong uint32_t sampleCount; 140965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleDuration; // time scale based 141965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong }; 142965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong bool mHasNegativeCttsDeltaDuration; 143965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t mNumCttsTableEntries; 144965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong List<CttsTableEntry> mCttsTableEntries; 145965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 1473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 1483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 1493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 1503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 1513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 1523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 1533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 1543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 1553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 1563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 1573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 1583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 1593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 162548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 16393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 1663c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 16770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mStartTimeRealUs; 16870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t mFirstSampleTimeRealUs; 16993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 17093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 17125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 172872a481558350634a3fd5cb67939de288af00ecbJames Dong // Update the audio track's drift information. 173872a481558350634a3fd5cb67939de288af00ecbJames Dong void updateDriftTime(const sp<MetaData>& meta); 174872a481558350634a3fd5cb67939de288af00ecbJames Dong 17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 17637187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 1793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 1803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 181b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size); 182b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size); 183b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size); 184215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 185215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 186faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 18793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 18803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 18919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 19019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 191c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 192c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 193c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 194c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 195c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 196c059860c73678a202bfa33062723e8f82fb779d9James Dong 197690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 198690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 19913f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t mRotation; 200690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 2021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 2031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 20479761ab096f57c3027fad9556c2bc436672d614eJames Dong 20579761ab096f57c3027fad9556c2bc436672d614eJames Dong // Duration is time scale based 20679761ab096f57c3027fad9556c2bc436672d614eJames Dong void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur); 207965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur); 20845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 20945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong bool isTrackMalFormed() const; 21043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong void sendTrackSummary(bool hasMultipleTracks); 2111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 212b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Write the boxes 213b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStcoBox(bool use32BitOffset); 214b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStscBox(); 215b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStszBox(); 216b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStssBox(); 217b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSttsBox(); 218965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong void writeCttsBox(); 219b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeD263Box(); 220b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writePaspBox(); 221b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAvccBox(); 222b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeUrlBox(); 223b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDrefBox(); 224b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDinfBox(); 225b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeDamrBox(); 226b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMdhdBox(time_t now); 227b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeSmhdBox(); 228b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVmhdBox(); 229b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeHdlrBox(); 230b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeTkhdBox(time_t now); 231b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4aEsdsBox(); 232b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeMp4vEsdsBox(); 233b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeAudioFourCCBox(); 234b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeVideoFourCCBox(); 235b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong void writeStblBox(bool use32BitOffset); 236b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 242674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(-1), 243674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(NO_INIT), 244b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 2451acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 246a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 247a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 248a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 249411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 25113aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 2527837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 25307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 25407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 25507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 25686b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 25786b7f47aa7482424cf8fd248f1315311919be3b0James Dong mStartTimeOffsetMs(-1) { 258674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong 25903f6f4e7e2ce09357cbc05bb546cd8a6e54b5baeJames Dong mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR); 260674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mFd >= 0) { 261674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck = OK; 262674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong } 26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26530ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 266674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong : mFd(dup(fd)), 267674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong mInitCheck(mFd < 0? NO_INIT: OK), 268b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 2691acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 270a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested(false), 271a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 272a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 273411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted(false), 27430ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 27513aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 2767837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 27707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mInterleaveDurationUs(1000000), 27807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000(0), 27907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000(0), 28086b7f47aa7482424cf8fd248f1315311919be3b0James Dong mAreGeoTagsAvailable(false), 28186b7f47aa7482424cf8fd248f1315311919be3b0James Dong mStartTimeOffsetMs(-1) { 28230ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 28330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 28420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 2881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 2901f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 2911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 296dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 297dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 298dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 299dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 300dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 301dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 302dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 303dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 304dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 305dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 306dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 307dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 308dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 309dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 310dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 311dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 312dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 313dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 314dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) const { 315dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 316dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 317dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 318dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 319dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 320dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 321dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 322dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 323dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 324dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 325dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 326dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 3272dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 328bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Mutex::Autolock l(mLock); 329bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong if (mStarted) { 330bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong LOGE("Attempt to add source AFTER recording is started"); 331bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong return UNKNOWN_ERROR; 332bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong } 333bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong Track *track = new Track(this, source, mTracks.size()); 33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 3352dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 3362dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 340a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 341a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 34293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 343a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 344a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 345a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 346a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 347a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 348a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 349a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 350a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 351a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 352a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 353a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 354a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 355a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 3562dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 3572dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 3582dec2b5be2056c6d9428897dc672185872d30d17James Dong // 3592dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 3602dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 3612dec2b5be2056c6d9428897dc672185872d30d17James Dong 36278a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2, 3632dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 36478a1a286f736888ae7af8860b2c424af0d978848James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 3 3652dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 3662dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 3672dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 3682dec2b5be2056c6d9428897dc672185872d30d17James Dong 3692dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 3702dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 3712dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 37278a1a286f736888ae7af8860b2c424af0d978848James Dong static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB 3732dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 3742dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 3752dec2b5be2056c6d9428897dc672185872d30d17James Dong 37678a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file size limit is set 377a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 37878a1a286f736888ae7af8860b2c424af0d978848James Dong size = mMaxFileSizeLimitBytes * 6 / 1000; 37978a1a286f736888ae7af8860b2c424af0d978848James Dong } 38078a1a286f736888ae7af8860b2c424af0d978848James Dong 38178a1a286f736888ae7af8860b2c424af0d978848James Dong // Max file duration limit is set 38278a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileDurationLimitUs != 0) { 38378a1a286f736888ae7af8860b2c424af0d978848James Dong if (bitRate > 0) { 38478a1a286f736888ae7af8860b2c424af0d978848James Dong int64_t size2 = 38578a1a286f736888ae7af8860b2c424af0d978848James Dong ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000); 38678a1a286f736888ae7af8860b2c424af0d978848James Dong if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) { 38778a1a286f736888ae7af8860b2c424af0d978848James Dong // When both file size and duration limits are set, 38878a1a286f736888ae7af8860b2c424af0d978848James Dong // we use the smaller limit of the two. 38978a1a286f736888ae7af8860b2c424af0d978848James Dong if (size > size2) { 39078a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 39178a1a286f736888ae7af8860b2c424af0d978848James Dong } 39278a1a286f736888ae7af8860b2c424af0d978848James Dong } else { 39378a1a286f736888ae7af8860b2c424af0d978848James Dong // Only max file duration limit is set 39478a1a286f736888ae7af8860b2c424af0d978848James Dong size = size2; 39578a1a286f736888ae7af8860b2c424af0d978848James Dong } 3962dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3972dec2b5be2056c6d9428897dc672185872d30d17James Dong } 39878a1a286f736888ae7af8860b2c424af0d978848James Dong 3992dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 4002dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 4012dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4022dec2b5be2056c6d9428897dc672185872d30d17James Dong 4032dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 4042dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 4052dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 4062dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 4072dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4082dec2b5be2056c6d9428897dc672185872d30d17James Dong 409a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 4102dec2b5be2056c6d9428897dc672185872d30d17James Dong " moov size %lld bytes", 4112dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 4122dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 4132dec2b5be2056c6d9428897dc672185872d30d17James Dong} 4142dec2b5be2056c6d9428897dc672185872d30d17James Dong 4152dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 416674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 41725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 420a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong /* 421a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * Check mMaxFileSizeLimitBytes at the beginning 422a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * since mMaxFileSizeLimitBytes may be implicitly 423a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * changed later for 32-bit file offset even if 424a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong * user does not ask to set it explicitly. 425a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong */ 426a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong if (mMaxFileSizeLimitBytes != 0) { 427a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong mIsFileSizeLimitExplicitlyRequested = true; 428a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong } 429a007e8229fb2be4866c483f9cd6c4af238a2da5eJames Dong 4302dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 4312dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 4322dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 4332dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 4342dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 4352dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4362dec2b5be2056c6d9428897dc672185872d30d17James Dong 4371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 4381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 4391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 4401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 4411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 4421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 4431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 4441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 4451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 446872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGW("32-bit file size limit (%lld bytes) too big. " 447d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong "It is changed to %lld bytes", 448d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 449d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 4501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 4511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 4521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 453b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 454b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 455b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 456b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 457b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 4582dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4592dec2b5be2056c6d9428897dc672185872d30d17James Dong 460065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 46193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 462a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 463a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 464a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 46593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 466a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 467a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 468a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 469a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 4708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 4718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 4728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 4738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 4748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 4758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("movie time scale: %d", mTimeScale); 4768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 4777837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = true; 4787837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 4797837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 4807837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 4817837c17063a4c50bc856ba59418516fdab731de7James Dong 482b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFtypBox(param); 48320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4847837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 48520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4867837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 4872dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 4882dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 4892dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 4902dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4912dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 4927837c17063a4c50bc856ba59418516fdab731de7James Dong } 4937837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mEstimatedMoovBoxSize >= 8); 494c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 4957837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize); 4967837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 4977837c17063a4c50bc856ba59418516fdab731de7James Dong 4987837c17063a4c50bc856ba59418516fdab731de7James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 4997837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 500c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 5011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 5021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 5031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 5041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 5051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 5061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 5071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 5081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 5091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 5101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 5111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 5121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 513a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 514a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 5161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 517a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 51825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 5221f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 5231f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 5241f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 52537187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 526674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 52737187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 528a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 529a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 53037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 531a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 532a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 53337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 53437187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 53537187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 53637187916a486504acaf83bea30147eb5fbf46ae5James Dong } 537a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 53837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 539a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 540a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 5411c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 542cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong LOGD("Stopping writer thread"); 543411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted) { 544411ba422e3635d534928ffd81abf54f4f291c739James Dong return; 545411ba422e3635d534928ffd81abf54f4f291c739James Dong } 5461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 5471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 5481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 5491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 5501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 5511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 5521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 5531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 5541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 5551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 556411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = false; 557cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong LOGD("Writer thread stopped"); 5581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 5591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 56013f6284305e4b27395a23db7882d670bdb1bcae1James Dong/* 56113f6284305e4b27395a23db7882d670bdb1bcae1James Dong * MP4 file standard defines a composition matrix: 56213f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | a b u | 56313f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | c d v | 56413f6284305e4b27395a23db7882d670bdb1bcae1James Dong * | x y w | 56513f6284305e4b27395a23db7882d670bdb1bcae1James Dong * 56613f6284305e4b27395a23db7882d670bdb1bcae1James Dong * the element in the matrix is stored in the following 56713f6284305e4b27395a23db7882d670bdb1bcae1James Dong * order: {a, b, u, c, d, v, x, y, w}, 56813f6284305e4b27395a23db7882d670bdb1bcae1James Dong * where a, b, c, d, x, and y is in 16.16 format, while 56913f6284305e4b27395a23db7882d670bdb1bcae1James Dong * u, v and w is in 2.30 format. 57013f6284305e4b27395a23db7882d670bdb1bcae1James Dong */ 57113f6284305e4b27395a23db7882d670bdb1bcae1James Dongvoid MPEG4Writer::writeCompositionMatrix(int degrees) { 57213f6284305e4b27395a23db7882d670bdb1bcae1James Dong LOGV("writeCompositionMatrix"); 57313f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t a = 0x00010000; 57413f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t b = 0; 57513f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t c = 0; 57613f6284305e4b27395a23db7882d670bdb1bcae1James Dong uint32_t d = 0x00010000; 57713f6284305e4b27395a23db7882d670bdb1bcae1James Dong switch (degrees) { 57813f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 0: 57913f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 58013f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 90: 58113f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 58213f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0x00010000; 58313f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0xFFFF0000; 58413f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 58513f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 58613f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 180: 58713f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0xFFFF0000; 58813f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0xFFFF0000; 58913f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 59013f6284305e4b27395a23db7882d670bdb1bcae1James Dong case 270: 59113f6284305e4b27395a23db7882d670bdb1bcae1James Dong a = 0; 59213f6284305e4b27395a23db7882d670bdb1bcae1James Dong b = 0xFFFF0000; 59313f6284305e4b27395a23db7882d670bdb1bcae1James Dong c = 0x00010000; 59413f6284305e4b27395a23db7882d670bdb1bcae1James Dong d = 0; 59513f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 59613f6284305e4b27395a23db7882d670bdb1bcae1James Dong default: 59713f6284305e4b27395a23db7882d670bdb1bcae1James Dong CHECK(!"Should never reach this unknown rotation"); 59813f6284305e4b27395a23db7882d670bdb1bcae1James Dong break; 59913f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 60013f6284305e4b27395a23db7882d670bdb1bcae1James Dong 60113f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(a); // a 60213f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(b); // b 60313f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // u 60413f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(c); // c 60513f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(d); // d 60613f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // v 60713f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // x 60813f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0); // y 60913f6284305e4b27395a23db7882d670bdb1bcae1James Dong writeInt32(0x40000000); // w 61013f6284305e4b27395a23db7882d670bdb1bcae1James Dong} 61113f6284305e4b27395a23db7882d670bdb1bcae1James Dong 612411ba422e3635d534928ffd81abf54f4f291c739James Dongvoid MPEG4Writer::release() { 613411ba422e3635d534928ffd81abf54f4f291c739James Dong close(mFd); 614411ba422e3635d534928ffd81abf54f4f291c739James Dong mFd = -1; 615411ba422e3635d534928ffd81abf54f4f291c739James Dong mInitCheck = NO_INIT; 616411ba422e3635d534928ffd81abf54f4f291c739James Dong mStarted = false; 617411ba422e3635d534928ffd81abf54f4f291c739James Dong} 61813f6284305e4b27395a23db7882d670bdb1bcae1James Dong 61937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::stop() { 620674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong if (mInitCheck != OK) { 62137187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 622411ba422e3635d534928ffd81abf54f4f291c739James Dong } else { 623411ba422e3635d534928ffd81abf54f4f291c739James Dong if (!mWriterThreadStarted || 624411ba422e3635d534928ffd81abf54f4f291c739James Dong !mStarted) { 625411ba422e3635d534928ffd81abf54f4f291c739James Dong if (mWriterThreadStarted) { 626411ba422e3635d534928ffd81abf54f4f291c739James Dong stopWriterThread(); 627411ba422e3635d534928ffd81abf54f4f291c739James Dong } 628411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 629411ba422e3635d534928ffd81abf54f4f291c739James Dong return OK; 630411ba422e3635d534928ffd81abf54f4f291c739James Dong } 63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 63337187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 6348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 63565b3d76025c71d755b0fb3b6ead90255f25417edJames Dong int64_t minDurationUs = 0x7fffffffffffffffLL; 63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 63837187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 63937187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 64037187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 64137187916a486504acaf83bea30147eb5fbf46ae5James Dong } 64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 6448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 6458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 64765b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (durationUs < minDurationUs) { 64865b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs = durationUs; 64965b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 65065b3d76025c71d755b0fb3b6ead90255f25417edJames Dong } 65165b3d76025c71d755b0fb3b6ead90255f25417edJames Dong 65265b3d76025c71d755b0fb3b6ead90255f25417edJames Dong if (mTracks.size() > 1) { 65365b3d76025c71d755b0fb3b6ead90255f25417edJames Dong LOGD("Duration from tracks range is [%lld, %lld] us", 65465b3d76025c71d755b0fb3b6ead90255f25417edJames Dong minDurationUs, maxDurationUs); 65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 6587837c17063a4c50bc856ba59418516fdab731de7James Dong 65937187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 66037187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 661411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 66237187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 66337187916a486504acaf83bea30147eb5fbf46ae5James Dong } 66437187916a486504acaf83bea30147eb5fbf46ae5James Dong 66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 6661acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 667c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset, SEEK_SET); 6681acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 669c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 4); 6701acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 671c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mMdatOffset + 8, SEEK_SET); 6721acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int64_t size = mOffset - mMdatOffset; 6731acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 674c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &size, 8); 6751acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 676c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 678c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong const off64_t moovOffset = mOffset; 6797837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = true; 6807837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 6817837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 6827837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMoovBox(maxDurationUs); 68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6857837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 6867837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 6877837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 6887837c17063a4c50bc856ba59418516fdab731de7James Dong 6897837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 690c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mFreeBoxOffset, SEEK_SET); 6917837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 692674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset); 6937837c17063a4c50bc856ba59418516fdab731de7James Dong 6947837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 695c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 6967837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 6977837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 6987837c17063a4c50bc856ba59418516fdab731de7James Dong 6997837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 7007837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 7017837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 7027837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 7032dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 7042dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("The mp4 file will not be streamable."); 7057837c17063a4c50bc856ba59418516fdab731de7James Dong } 7067837c17063a4c50bc856ba59418516fdab731de7James Dong 7070c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 709411ba422e3635d534928ffd81abf54f4f291c739James Dong release(); 71037187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 713b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMvhdBox(int64_t durationUs) { 714b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong time_t now = time(NULL); 715b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("mvhd"); 716b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // version=0, flags=0 717b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // creation time 718b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(now); // modification time 719b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTimeScale); // mvhd timescale 720b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6; 721b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(duration); 722b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0x10000); // rate: 1.0 723b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0x100); // volume 724b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt16(0); // reserved 725b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 726b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // reserved 727b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeCompositionMatrix(0); // matrix 728b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 729b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 730b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 731b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 732b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 733b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); // predefined 734b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(mTracks.size() + 1); // nextTrackID 735b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // mvhd 736b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 737b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 738b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::writeMoovBox(int64_t durationUs) { 739b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("moov"); 740b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMvhdBox(durationUs); 74107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (mAreGeoTagsAvailable) { 74207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeUdtaBox(); 74307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 744b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t id = 1; 745b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<Track *>::iterator it = mTracks.begin(); 746b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mTracks.end(); ++it, ++id) { 747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (*it)->writeTrackHeader(mUse32BitOffset); 748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); // moov 750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 7522cf9c5073ca3342ee52673ad68763fadd2c2be79James Dongvoid MPEG4Writer::writeFtypBox(MetaData *param) { 753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong beginBox("ftyp"); 754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t fileType; 756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (param && param->findInt32(kKeyFileType, &fileType) && 757b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fileType != OUTPUT_FORMAT_MPEG_4) { 758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeInt32(0); 764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("isom"); 765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeFourcc("3gp4"); 766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong endBox(); 767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 76907ec01904613a0bac32caaa8444b4690998faed7James Dongstatic bool isTestModeEnabled() { 77007ec01904613a0bac32caaa8444b4690998faed7James Dong#if (PROPERTY_VALUE_MAX < 5) 77107ec01904613a0bac32caaa8444b4690998faed7James Dong#error "PROPERTY_VALUE_MAX must be at least 5" 77207ec01904613a0bac32caaa8444b4690998faed7James Dong#endif 77307ec01904613a0bac32caaa8444b4690998faed7James Dong 77407ec01904613a0bac32caaa8444b4690998faed7James Dong // Test mode is enabled only if rw.media.record.test system 77507ec01904613a0bac32caaa8444b4690998faed7James Dong // property is enabled. 77607ec01904613a0bac32caaa8444b4690998faed7James Dong char value[PROPERTY_VALUE_MAX]; 77707ec01904613a0bac32caaa8444b4690998faed7James Dong if (property_get("rw.media.record.test", value, NULL) && 77807ec01904613a0bac32caaa8444b4690998faed7James Dong (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 77907ec01904613a0bac32caaa8444b4690998faed7James Dong return true; 78007ec01904613a0bac32caaa8444b4690998faed7James Dong } 78107ec01904613a0bac32caaa8444b4690998faed7James Dong return false; 78207ec01904613a0bac32caaa8444b4690998faed7James Dong} 78307ec01904613a0bac32caaa8444b4690998faed7James Dong 78470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dongvoid MPEG4Writer::sendSessionSummary() { 78507ec01904613a0bac32caaa8444b4690998faed7James Dong // Send session summary only if test mode is enabled 78607ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 78707ec01904613a0bac32caaa8444b4690998faed7James Dong return; 78807ec01904613a0bac32caaa8444b4690998faed7James Dong } 78907ec01904613a0bac32caaa8444b4690998faed7James Dong 79070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 79170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it != mChunkInfos.end(); ++it) { 79270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int trackNum = it->mTrack->getTrackId() << 28; 79370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 79470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS, 79570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs); 79670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 79770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong} 79870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 79913aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 80013aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 80113aec890216948b0c364f8f92792129d0335f506James Dong return OK; 80213aec890216948b0c364f8f92792129d0335f506James Dong} 80313aec890216948b0c364f8f92792129d0335f506James Dong 80413aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 80513aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 80613aec890216948b0c364f8f92792129d0335f506James Dong} 80713aec890216948b0c364f8f92792129d0335f506James Dong 80813aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 80913aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 81013aec890216948b0c364f8f92792129d0335f506James Dong} 81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 812c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 813c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 815c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 816c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 817c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong buffer->range_length()); 81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 82403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 82503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 82603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 82703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 82803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 82903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 83003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 83103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 83203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 83303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 83403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 83503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 83603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 83703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 838c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongoff64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 839c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t old_offset = mOffset; 84030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 84130ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 84203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 843b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 844b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 845c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 846b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 847c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 848b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 849c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 850b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 851c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 852c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong 853c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, 854c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong (const uint8_t *)buffer->data() + buffer->range_offset(), 855c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong length); 856b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 857b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 858b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 859b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong CHECK(length < 65536); 86030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 861b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 862c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 863b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 864c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, &x, 1); 865c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length); 866b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 867b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 86830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 86930ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 87030ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 87130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 8727837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 873674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong const void *ptr, size_t size, size_t nmemb) { 8747837c17063a4c50bc856ba59418516fdab731de7James Dong 8757837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 8767837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 877674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong // This happens only when we write the moov box at the end of 878674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong // recording, not for each output video/audio frame we receive. 879c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 8801acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 881c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong for (List<off64_t>::iterator it = mBoxes.begin(); 8827837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 8837837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 8847837c17063a4c50bc856ba59418516fdab731de7James Dong } 885674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong lseek64(mFd, mOffset, SEEK_SET); 886674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); 887674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 8887837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 8897837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 8907837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 8917837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 8927837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 8937837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = false; 8947837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 8957837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 8967837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 8977837c17063a4c50bc856ba59418516fdab731de7James Dong } 8987837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 899674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong ::write(mFd, ptr, size * nmemb); 9007837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 9017837c17063a4c50bc856ba59418516fdab731de7James Dong } 9027837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 9037837c17063a4c50bc856ba59418516fdab731de7James Dong} 9047837c17063a4c50bc856ba59418516fdab731de7James Dong 90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 9060c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9087837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 9097837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 91520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 9160c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 91720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 918c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = *--mBoxes.end(); 91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9217837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 9227837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 9237837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 9247837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 925c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, offset, SEEK_SET); 9267837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 9277837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 928c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong lseek64(mFd, mOffset, SEEK_SET); 9297837c17063a4c50bc856ba59418516fdab731de7James Dong } 93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 933674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 1); 93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 93520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 93620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 93720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 938674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 2); 93920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 94120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 943674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 4); 94420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 94520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 94620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 94720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 948674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(&x, 1, 8); 94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 953674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, n + 1); 95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 9570c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 958674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(s, 1, 4); 95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 96107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 96207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/-DD.DDDD format 96307b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLatitude(int degreex10000) { 96407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 96507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 96607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 96707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 96807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[9]; 96907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 97007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 97107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%c%.2d.", sign, wholePart); 97207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 97307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 5, "%+.2d.", wholePart); 97407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 97507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 97607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 97707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 97807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 97907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 98007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 98107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[4], 5, "%.4d", fractionalPart); 98207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 98307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 98407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 8); 98507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 98607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 98707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong// Written in +/- DDD.DDDD format 98807b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeLongitude(int degreex10000) { 98907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong bool isNegative = (degreex10000 < 0); 99007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char sign = isNegative? '-': '+'; 99107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 99207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the whole part 99307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong char str[10]; 99407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int wholePart = degreex10000 / 10000; 99507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (wholePart == 0) { 99607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%c%.3d.", sign, wholePart); 99707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } else { 99807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(str, 6, "%+.3d.", wholePart); 99907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 100007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 100107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Handle the fractional part 100207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong int fractionalPart = degreex10000 - (wholePart * 10000); 100307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (fractionalPart < 0) { 100407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong fractionalPart = -fractionalPart; 100507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 100607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong snprintf(&str[5], 5, "%.4d", fractionalPart); 100707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 100807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Do not write the null terminator 100907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong write(str, 1, 9); 101007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 101107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 101207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 101307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 101407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * latitudex10000 is latitude in degrees times 10000, and 101507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * longitudex10000 is longitude in degrees times 10000. 101607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the latitude is in [-90, +90], and 101707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * The range for the longitude is in [-180, +180] 101807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 101907b1bb529a1ae76c46a71b01338c166f9490629dJames Dongstatus_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) { 102007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong // Is latitude or longitude out of range? 102107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong if (latitudex10000 < -900000 || latitudex10000 > 900000 || 102207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong longitudex10000 < -1800000 || longitudex10000 > 1800000) { 102307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return BAD_VALUE; 102407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong } 102507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 102607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLatitudex10000 = latitudex10000; 102707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mLongitudex10000 = longitudex10000; 102807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong mAreGeoTagsAvailable = true; 102907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong return OK; 103007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 103107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 1033674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong write(data, 1, size); 103420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 103520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 103678a1a286f736888ae7af8860b2c424af0d978848James Dongbool MPEG4Writer::isFileStreamable() const { 103778a1a286f736888ae7af8860b2c424af0d978848James Dong return mStreamableFile; 103878a1a286f736888ae7af8860b2c424af0d978848James Dong} 103978a1a286f736888ae7af8860b2c424af0d978848James Dong 1040d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 1041d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1042d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 1043d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1044d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1045d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1046956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 1047d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1048d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1049d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 1050d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 10511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1052acd234bba9f048971d66890009eeff9a8db94be3James Dong // Be conservative in the estimate: do not exceed 95% of 1053acd234bba9f048971d66890009eeff9a8db94be3James Dong // the target file limit. For small target file size limit, though, 1054acd234bba9f048971d66890009eeff9a8db94be3James Dong // this will not help. 1055acd234bba9f048971d66890009eeff9a8db94be3James Dong return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100); 1056d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1057d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1058d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 1059d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 1060d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 1061d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1062d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1063d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1064d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 1065d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 1066d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 1067d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 1068d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1069d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1070d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 1071d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1072d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 107325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 107425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 107525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 107625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 107725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 107825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 107925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 108025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 108125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 108225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 108325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 108425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 108525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 1086f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 1087f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("setStartTimestampUs: %lld", timeUs); 1088f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong CHECK(timeUs >= 0); 10893c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 1090065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 1091f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 1092f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("Earliest track starting time: %lld", mStartTimestampUs); 10933c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 10943c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 10953c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 1096f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 10973c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 10983c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 10993c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 11003c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 110158ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 110258ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 110358ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 110458ae9c530247668f8af36e30d228c716c226b3d4James Dong} 110558ae9c530247668f8af36e30d228c716c226b3d4James Dong 110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 110820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 1109bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId) 111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 111125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 111220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 111320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 1114a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 1115a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 1116eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted(false), 1117bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mTrackId(trackId), 1118c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 1119956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 1120be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 112225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 1123548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 112413f6284305e4b27395a23db7882d670bdb1bcae1James Dong mReachedEOS(false), 112513f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation(0) { 112619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 11278f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 11281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 11291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 11301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 11311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 11321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 11331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 11341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1135c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 1136c059860c73678a202bfa33062723e8f82fb779d9James Dong} 1137c059860c73678a202bfa33062723e8f82fb779d9James Dong 11381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 11391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 11401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset() 11411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ? mNumStcoTableEntries * 4 11421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong : mNumStcoTableEntries * 8; 11431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 11441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4); 11451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 114678a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size 114778a1a286f736888ae7af8860b2c424af0d978848James Dong if (!mOwner->isFileStreamable()) { 114878a1a286f736888ae7af8860b2c424af0d978848James Dong // Reserved free space is not large enough to hold 114978a1a286f736888ae7af8860b2c424af0d978848James Dong // all meta data and thus wasted. 115078a1a286f736888ae7af8860b2c424af0d978848James Dong mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 + // stsc box size 115178a1a286f736888ae7af8860b2c424af0d978848James Dong mNumStssTableEntries * 4 + // stss box size 115278a1a286f736888ae7af8860b2c424af0d978848James Dong mNumSttsTableEntries * 8 + // stts box size 1153965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mNumCttsTableEntries * 8 + // ctts box size 115478a1a286f736888ae7af8860b2c424af0d978848James Dong stcoBoxSizeBytes + // stco box size 115578a1a286f736888ae7af8860b2c424af0d978848James Dong stszBoxSizeBytes; // stsz box size 115678a1a286f736888ae7af8860b2c424af0d978848James Dong } 11571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 11581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 11591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 11601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 11611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 11621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong StscTableEntry stscEntry(chunkId, sampleId, 1); 11631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mStscTableEntries.push_back(stscEntry); 11641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStscTableEntries; 11651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 11661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 11671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 11681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mStssTableEntries.push_back(sampleId); 11691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStssTableEntries; 11701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 11711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 11721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 117379761ab096f57c3027fad9556c2bc436672d614eJames Dong size_t sampleCount, int32_t duration) { 11741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 117579761ab096f57c3027fad9556c2bc436672d614eJames Dong SttsTableEntry sttsEntry(sampleCount, duration); 11761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mSttsTableEntries.push_back(sttsEntry); 11771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumSttsTableEntries; 11781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 11791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1180965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::addOneCttsTableEntry( 1181965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong size_t sampleCount, int32_t duration) { 1182965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1183965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { 1184965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 1185965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1186965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (duration < 0 && !mHasNegativeCttsDeltaDuration) { 1187965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mHasNegativeCttsDeltaDuration = true; 1188965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1189965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CttsTableEntry cttsEntry(sampleCount, duration); 1190965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mCttsTableEntries.push_back(cttsEntry); 1191965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong ++mNumCttsTableEntries; 1192965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 1193965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 1194c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongvoid MPEG4Writer::Track::addChunkOffset(off64_t offset) { 11951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStcoTableEntries; 11961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mChunkOffsets.push_back(offset); 11971f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 11981f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1199c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 1200c059860c73678a202bfa33062723e8f82fb779d9James Dong LOGV("setTimeScale"); 1201c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 1202c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 1203c059860c73678a202bfa33062723e8f82fb779d9James Dong 1204c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 1205c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 1206c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 1207c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 1208c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 1209c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 1210c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1211c059860c73678a202bfa33062723e8f82fb779d9James Dong 1212c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 1213c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 1214c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 1215c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 1216c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1217c059860c73678a202bfa33062723e8f82fb779d9James Dong 12188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 121919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 122019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 122119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 122219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 122319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 122419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 122519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 122619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 122719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 122819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 122919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 123019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 123119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 123219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 123319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 123419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 123519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 123619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 123719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 123819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 123919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 124019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 124119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 124219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 124319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 124419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 124519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 124619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 124719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 124819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 124919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 125220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 125920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 126193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 126293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("initTrackingProgressStatus"); 126393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 126493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 126593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 126693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 126793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 126893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 126993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Receive request to track progress status for every %lld us", timeUs); 127093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 127193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 127293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 127393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 127493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 127593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 12761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 12771c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 12781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("ThreadWrapper: %p", me); 12791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 12801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 12811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 12821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 12831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 12841c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 12851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("bufferChunk: %p", chunk.mTrack); 12861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 12871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 12881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 12891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 12901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 12911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 12921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 12931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 12941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 12951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 12961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 12971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 12981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 12991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK("Received a chunk for a unknown track" == 0); 13001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 13011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1302fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeChunkToFile(Chunk* chunk) { 1303fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong LOGV("writeChunkToFile: %lld from %s track", 1304fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk.mTimestampUs, chunk.mTrack->isAudio()? "audio": "video"); 1305fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1306fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong int32_t isFirstSample = true; 1307fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!chunk->mSamples.empty()) { 1308fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); 1309fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1310fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong off64_t offset = chunk->mTrack->isAvc() 1311fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong ? addLengthPrefixedSample_l(*it) 1312fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong : addSample_l(*it); 1313fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1314fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (isFirstSample) { 1315fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mTrack->addChunkOffset(offset); 1316fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong isFirstSample = false; 13171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 13181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 13191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 13201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 1321fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.erase(it); 13221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1323fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong chunk->mSamples.clear(); 13241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 13251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1326fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongvoid MPEG4Writer::writeAllChunks() { 1327fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong LOGV("writeAllChunks"); 13281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 132970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong Chunk chunk; 133070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong while (findChunkToWrite(&chunk)) { 1331e9f6d0579603372fd2547e6c5ba6e114c6f8cba7James Dong writeChunkToFile(&chunk); 133270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong ++outstandingChunks; 13331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 133470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 133570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong sendSessionSummary(); 133670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 13371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 13381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGD("%d chunks are written in the last batch", outstandingChunks); 13391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 13401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1341fcac8fa9421f442f024018628a6042d7a14fbfb0James Dongbool MPEG4Writer::findChunkToWrite(Chunk *chunk) { 1342fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong LOGV("findChunkToWrite"); 13431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 13441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 13451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 13461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 13471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 13481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 13491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 13501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 13511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 13521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 13531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 13541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 13551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 13561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 13571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 13581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("Nothing to be written after all"); 1359fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 13601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 13611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 13621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 13631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 13641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1365fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 13661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 13671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 13681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 1369fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong *chunk = *(it->mChunks.begin()); 1370fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong it->mChunks.erase(it->mChunks.begin()); 1371fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong CHECK_EQ(chunk->mTrack, track); 137270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 137370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t interChunkTimeUs = 137470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong chunk->mTimeStampUs - it->mPrevChunkTimestampUs; 137570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (interChunkTimeUs > it->mPrevChunkTimestampUs) { 137670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong it->mMaxInterChunkDurUs = interChunkTimeUs; 137770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 137870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 1379fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return true; 13801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 13811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1382fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1383fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong return false; 13841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 13851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 13861c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 13871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("threadFunc"); 13881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1389a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); 1390fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1391fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Mutex::Autolock autoLock(mLock); 13921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 1393fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong Chunk chunk; 1394fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong bool chunkFound = false; 1395fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1396fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { 13971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 13981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 13991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 1400fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong // Actual write without holding the lock in order to 1401fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong // reduce the blocking time for media track threads. 1402fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong if (chunkFound) { 1403fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong mLock.unlock(); 1404fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeChunkToFile(&chunk); 1405fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong mLock.lock(); 1406fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong } 14071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 1408fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong 1409fcac8fa9421f442f024018628a6042d7a14fbfb0James Dong writeAllChunks(); 14101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 14111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14121c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 14131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("startWriterThread"); 14141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 14161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1417e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 14181c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 14191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 14201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 14211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 142270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mPrevChunkTimestampUs = 0; 142370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong info.mMaxInterChunkDurUs = 0; 14241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 14251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 14261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 14281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 14291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 14301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 14311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 1432411ba422e3635d534928ffd81abf54f4f291c739James Dong mWriterThreadStarted = true; 14331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 14341c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 14351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 14361f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 143793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1438a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1439a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1440a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1441a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1442a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 144325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 144493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 144519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 144619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 144719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 144870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mStartTimeRealUs = startTimeUs; 144919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 145013f6284305e4b27395a23db7882d670bdb1bcae1James Dong int32_t rotationDegrees; 145113f6284305e4b27395a23db7882d670bdb1bcae1James Dong if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) { 145213f6284305e4b27395a23db7882d670bdb1bcae1James Dong mRotation = rotationDegrees; 145313f6284305e4b27395a23db7882d670bdb1bcae1James Dong } 145413f6284305e4b27395a23db7882d670bdb1bcae1James Dong 14555b6a01e65aa4129a9226667536d1bc1dad5980d8James Dong mIsRealTimeRecording = true; 1456e259531ce59ab1f31de5a23124b22536f6a5a767James Dong { 1457e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int32_t isNotRealTime; 1458e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) { 1459e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mIsRealTimeRecording = (isNotRealTime == 0); 1460e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1461e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1462e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 146393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 146493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1465f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1466a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (mIsRealTimeRecording && mOwner->numTracks() > 1) { 1467a472613aec322e25891abf5c77bf3f7e3c244920James Dong /* 1468a472613aec322e25891abf5c77bf3f7e3c244920James Dong * This extra delay of accepting incoming audio/video signals 1469a472613aec322e25891abf5c77bf3f7e3c244920James Dong * helps to align a/v start time at the beginning of a recording 1470a472613aec322e25891abf5c77bf3f7e3c244920James Dong * session, and it also helps eliminate the "recording" sound for 1471a472613aec322e25891abf5c77bf3f7e3c244920James Dong * camcorder applications. 1472a472613aec322e25891abf5c77bf3f7e3c244920James Dong * 147386b7f47aa7482424cf8fd248f1315311919be3b0James Dong * If client does not set the start time offset, we fall back to 147486b7f47aa7482424cf8fd248f1315311919be3b0James Dong * use the default initial delay value. 1475a472613aec322e25891abf5c77bf3f7e3c244920James Dong */ 147686b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 147786b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 147886b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 147986b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 148086b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeUs += startTimeOffsetUs; 148186b7f47aa7482424cf8fd248f1315311919be3b0James Dong LOGI("Start time offset: %lld us", startTimeOffsetUs); 1482a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 1483a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1484f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1485a472613aec322e25891abf5c77bf3f7e3c244920James Dong 1486f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 148725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 148825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 148925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 149025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 149320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 149420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 149520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 149620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1497eaae38445a340c4857c1c5569475879a728e63b7James Dong mStarted = true; 1498c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 149925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1500956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 15011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStcoTableEntries = 0; 15021f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStssTableEntries = 0; 15031f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStscTableEntries = 0; 15041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumSttsTableEntries = 0; 1505965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mNumCttsTableEntries = 0; 15061f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 1507f2ab12d0dcef27fd52dcae53221e9c51a369fef6James Dong 150843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = 0; 1509965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mHasNegativeCttsDeltaDuration = false; 151020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 151125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 151220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 151325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 151425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 151520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 151620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 151737187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1518a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 151937187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1520a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1521a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 152237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 1523cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong LOGD("Stopping %s track", mIsAudio? "Audio": "Video"); 1524eaae38445a340c4857c1c5569475879a728e63b7James Dong if (!mStarted) { 1525eaae38445a340c4857c1c5569475879a728e63b7James Dong LOGE("Stop() called but track is not started"); 1526eaae38445a340c4857c1c5569475879a728e63b7James Dong return ERROR_END_OF_STREAM; 1527eaae38445a340c4857c1c5569475879a728e63b7James Dong } 1528eaae38445a340c4857c1c5569475879a728e63b7James Dong 152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 153037187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 153737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = (status_t) dummy; 153837187916a486504acaf83bea30147eb5fbf46ae5James Dong 1539cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong LOGD("Stopping %s track source", mIsAudio? "Audio": "Video"); 154037187916a486504acaf83bea30147eb5fbf46ae5James Dong { 154137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = mSource->stop(); 154237187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK && status != ERROR_END_OF_STREAM) { 154337187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 154437187916a486504acaf83bea30147eb5fbf46ae5James Dong } 154537187916a486504acaf83bea30147eb5fbf46ae5James Dong } 154637187916a486504acaf83bea30147eb5fbf46ae5James Dong 1547cb09c03450bb09304ad5afd2d223254bf2e6e38cJames Dong LOGD("%s track stopped", mIsAudio? "Audio": "Video"); 154837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 154920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 155020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 155125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 155225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 155325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 155425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 155520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 155620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 155720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 155820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 155937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 156037187916a486504acaf83bea30147eb5fbf46ae5James Dong return (void *) err; 156120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 156220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 15643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("getNalUnitType: %d", byte); 15653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 15673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 15683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 15693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 15713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 15723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("findNextStartCode: %p %d", data, length); 15743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 15763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 15773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 15783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 15793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 15813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 15823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 15843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 15853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 15873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 15883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("parseParamSet"); 15903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 15913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 15923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 15943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 15953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 15963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Param set is malformed, since its length is 0"); 15973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 15983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 15993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 16013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 16023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 16033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Seq parameter set malformed"); 16043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 16053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 16073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 16083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 16093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 16103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 16113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 16123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 16133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 16143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Inconsistent profile/level found in seq parameter sets"); 16153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 16163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 16193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 16203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 16213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 16233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 16243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 16263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 16273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("copyAVCCodecSpecificData"); 16283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 16303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 16313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 16323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Codec specific data length too short: %d", size); 16333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 16343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 16373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 16383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 16393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 16403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 16413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 16433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 16443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("parseAVCCodecSpecificData"); 16463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 16473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 16483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 16493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 16503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 16513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 16523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 16533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 16543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 16553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 16563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 16573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 16583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 16593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 16603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 16613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("SPS must come before PPS"); 16623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 16633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 16653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 16663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 16683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 16693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 16703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("SPS must come before PPS"); 16713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 16723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 16743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 16753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 16773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 16783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Only SPS and PPS Nal units are expected"); 16793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 16803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 16833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 16843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 16873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 16883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 16893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 16903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 16923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 16933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 16943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 16953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 16963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Cound not find sequence parameter set"); 16973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 16983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 16993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 17013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 17023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 17033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 17073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 17083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 17093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 17103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Cound not find picture parameter set"); 17113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 17123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 17143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Too many pic parameter sets (%d) found", nPicParamSets); 17153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 17163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 17203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 17213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 17223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 17233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 17243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 17253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 17263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 17303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 1731548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 173203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 173303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 1734548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 173503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 1736548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Already have codec specific data"); 173703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 173803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 173903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 17403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 17413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Codec specific data length too short: %d", size); 174203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 174303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 174403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 17453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 17463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 17473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 174803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 174903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 17503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 175103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 175203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 175303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 17543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 17553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 175603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 175703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 17583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 17593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 17603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 17613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 176203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 17633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 1764b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 1765b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 1766b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 1767b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 1768b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 176903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 17703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 17713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 17723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 17733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 17743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 17753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 17763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 17773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 17783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 17793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 17803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 17823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 17833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 17843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 17853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 17873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 17883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 17893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 17903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 17913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 17923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 17933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 17943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 17953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 17963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 17973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 17983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 17993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 18003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 180103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 180203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 180303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 180403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 1805872a481558350634a3fd5cb67939de288af00ecbJames Dong/* 1806872a481558350634a3fd5cb67939de288af00ecbJames Dong * Updates the drift time from the audio track so that 1807872a481558350634a3fd5cb67939de288af00ecbJames Dong * the video track can get the updated drift time information 1808872a481558350634a3fd5cb67939de288af00ecbJames Dong * from the file writer. The fluctuation of the drift time of the audio 1809872a481558350634a3fd5cb67939de288af00ecbJames Dong * encoding path is smoothed out with a simple filter by giving a larger 1810872a481558350634a3fd5cb67939de288af00ecbJames Dong * weight to more recently drift time. The filter coefficients, 0.5 and 0.5, 1811872a481558350634a3fd5cb67939de288af00ecbJames Dong * are heuristically determined. 1812872a481558350634a3fd5cb67939de288af00ecbJames Dong */ 1813872a481558350634a3fd5cb67939de288af00ecbJames Dongvoid MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) { 1814872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t driftTimeUs = 0; 1815872a481558350634a3fd5cb67939de288af00ecbJames Dong if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) { 1816872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t prevDriftTimeUs = mOwner->getDriftTimeUs(); 1817872a481558350634a3fd5cb67939de288af00ecbJames Dong int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1; 1818872a481558350634a3fd5cb67939de288af00ecbJames Dong mOwner->setDriftTimeUs(timeUs); 1819872a481558350634a3fd5cb67939de288af00ecbJames Dong } 1820872a481558350634a3fd5cb67939de288af00ecbJames Dong} 1821872a481558350634a3fd5cb67939de288af00ecbJames Dong 182237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 182330ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 182413aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 182543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong const bool hasMultipleTracks = (mOwner->numTracks() > 1); 182613aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 182713aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 182813aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 1829965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastTimestampUs = 0; // Previous sample time stamp 1830965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastCttsTimeUs = 0; // Previous sample time stamp 1831965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationUs = 0; // Between the previous two samples 1832965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currDurationTicks = 0; // Timescale based ticks 1833965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastDurationTicks = 0; // Timescale based ticks 1834965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 1835965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t currCttsDurTicks = 0; // Timescale based ticks 1836965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t lastCttsDurTicks = 0; // Timescale based ticks 1837965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int32_t cttsSampleCount = 1; // Sample count in the current ctts table entry 1838965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 1839a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 1840965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timestampUs = 0; 1841965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t cttsDeltaTimeUs = 0; 184205e65807d48c2c7b954af82eda0532a48948e96aJames Dong bool hasBFrames = false; 1843e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 184405e65807d48c2c7b954af82eda0532a48948e96aJames Dong#if 1 184505e65807d48c2c7b954af82eda0532a48948e96aJames Dong // XXX: Samsung's video encoder's output buffer timestamp 184605e65807d48c2c7b954af82eda0532a48948e96aJames Dong // is not correct. see bug 4724339 184705e65807d48c2c7b954af82eda0532a48948e96aJames Dong char value[PROPERTY_VALUE_MAX]; 184805e65807d48c2c7b954af82eda0532a48948e96aJames Dong if (property_get("rw.media.record.hasb", value, NULL) && 184905e65807d48c2c7b954af82eda0532a48948e96aJames Dong (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) { 185005e65807d48c2c7b954af82eda0532a48948e96aJames Dong hasBFrames = true; 185105e65807d48c2c7b954af82eda0532a48948e96aJames Dong } 185205e65807d48c2c7b954af82eda0532a48948e96aJames Dong#endif 1853a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong if (mIsAudio) { 1854a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0); 1855a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } else { 1856a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0); 1857a6f61fc8e3d06373c17f0a38ff600e2b71c414faJames Dong } 185886106f8b0641444c97a39e9788eeef55ab2a2ac6Glenn Kasten androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 1859985f838934510983d8a887461e98dca60a6e858fJames Dong 1860d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 186120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1862ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mNumSamples = 0; 186393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 186420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 186593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 186620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 186720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 186820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 186913aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 187020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 187120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 187220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1873a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 1874a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 1875a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 1876a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 1877a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 1878a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 1879a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 1880a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1881a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 188230ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 188330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 188403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 188503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 188603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 1887548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 1888548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 18891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 189003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 189103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 189203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 189303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 1894be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 18951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 189603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 189703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 189803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 189903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 190003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 190103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 190230ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 190330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 190430ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 190530ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 190630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1907548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 190830ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 1909a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1910a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1911d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 1912d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 1913d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 1914d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 1915d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 1916d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 1917d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 1918d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 1919d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 1920d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 19211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 1922e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 1923b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 1924b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mIsAvc) { 1925b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 1926b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 1927b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 1928b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 1929b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 1930b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 1931050b28a593350047845a45a14cc5026221ac1620James Dong 1932d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 19331f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 19341f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 19351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1936d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 1937d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 1938d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1939d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1940d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 1941d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 1942d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1943d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1944d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1945050b28a593350047845a45a14cc5026221ac1620James Dong 1946d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 1947d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 1948d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 1949d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1950d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 195170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mNumSamples == 0) { 195270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mFirstSampleTimeRealUs = systemTime() / 1000; 1953f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 1954f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 19558428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs = mStartTimestampUs; 19563c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 195748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 1958a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 19598428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs; 19608428af5381e835cc783b7ecb0d71cb60961c99c2James Dong CHECK(durExcludingEarlierPausesUs >= 0); 19618428af5381e835cc783b7ecb0d71cb60961c99c2James Dong int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs; 19628428af5381e835cc783b7ecb0d71cb60961c99c2James Dong CHECK(pausedDurationUs >= lastDurationUs); 19638428af5381e835cc783b7ecb0d71cb60961c99c2James Dong previousPausedDurationUs += pausedDurationUs - lastDurationUs; 1964a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 1965a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1966a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1967a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 19688428af5381e835cc783b7ecb0d71cb60961c99c2James Dong CHECK(timestampUs >= 0); 196905e65807d48c2c7b954af82eda0532a48948e96aJames Dong if (!mIsAudio && hasBFrames) { 1970965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong /* 1971965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time: timestampUs 1972965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Decoding time: decodingTimeUs 1973965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * Composition time delta = composition time - decoding time 1974965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * 1975965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * We save picture decoding time stamp delta in stts table entries, 1976965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong * and composition time delta duration in ctts table entries. 1977965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong */ 1978965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t decodingTimeUs; 1979965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); 1980965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong decodingTimeUs -= previousPausedDurationUs; 1981965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t timeUs = decodingTimeUs; 1982965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong cttsDeltaTimeUs = timestampUs - decodingTimeUs; 1983965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs = decodingTimeUs; 1984965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong LOGV("decoding time: %lld and ctts delta time: %lld", 1985965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong timestampUs, cttsDeltaTimeUs); 1986965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 1987872a481558350634a3fd5cb67939de288af00ecbJames Dong 1988872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsRealTimeRecording) { 1989872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 1990872a481558350634a3fd5cb67939de288af00ecbJames Dong updateDriftTime(meta_data); 1991e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1992e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1993872a481558350634a3fd5cb67939de288af00ecbJames Dong 1994e259531ce59ab1f31de5a23124b22536f6a5a767James Dong CHECK(timestampUs >= 0); 19958428af5381e835cc783b7ecb0d71cb60961c99c2James Dong LOGV("%s media time stamp: %lld and previous paused duration %lld", 19968428af5381e835cc783b7ecb0d71cb60961c99c2James Dong mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs); 1997c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 1998c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 19993b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 20003b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 20018644c14618d30d9e57a69df40ed939986ebf02c4James Dong mSampleSizes.push_back(sampleSize); 2002ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong ++mNumSamples; 2003ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples > 2) { 2004c059860c73678a202bfa33062723e8f82fb779d9James Dong // We need to use the time scale based ticks, rather than the 2005c059860c73678a202bfa33062723e8f82fb779d9James Dong // timestamp itself to determine whether we have to use a new 2006c059860c73678a202bfa33062723e8f82fb779d9James Dong // stts entry, since we may have rounding errors. 2007c059860c73678a202bfa33062723e8f82fb779d9James Dong // The calculation is intended to reduce the accumulated 2008c059860c73678a202bfa33062723e8f82fb779d9James Dong // rounding errors. 2009c059860c73678a202bfa33062723e8f82fb779d9James Dong currDurationTicks = 2010c059860c73678a202bfa33062723e8f82fb779d9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 2011c059860c73678a202bfa33062723e8f82fb779d9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2012c059860c73678a202bfa33062723e8f82fb779d9James Dong 2013a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Force the first sample to have its own stts entry so that 2014a472613aec322e25891abf5c77bf3f7e3c244920James Dong // we can adjust its value later to maintain the A/V sync. 2015a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (mNumSamples == 3 || currDurationTicks != lastDurationTicks) { 2016a472613aec322e25891abf5c77bf3f7e3c244920James Dong LOGV("%s lastDurationUs: %lld us, currDurationTicks: %lld us", 2017a472613aec322e25891abf5c77bf3f7e3c244920James Dong mIsAudio? "Audio": "Video", lastDurationUs, currDurationTicks); 201879761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2019be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 2020be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2021be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 2022be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2023965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2024965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (!mIsAudio) { 2025965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong currCttsDurTicks = 2026965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong ((cttsDeltaTimeUs * mTimeScale + 500000LL) / 1000000LL - 2027965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong (lastCttsTimeUs * mTimeScale + 500000LL) / 1000000LL); 2028965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (currCttsDurTicks != lastCttsDurTicks) { 2029965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks); 2030965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong cttsSampleCount = 1; 2031965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } else { 2032965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong ++cttsSampleCount; 2033965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2034965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2035be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2036be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 2037ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples >= 2 && previousSampleSize != sampleSize) { 2038be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 2039be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 20408644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 2041be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2042a472613aec322e25891abf5c77bf3f7e3c244920James Dong LOGV("%s timestampUs/lastTimestampUs: %lld/%lld", 2043a472613aec322e25891abf5c77bf3f7e3c244920James Dong mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs); 20448644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 2045c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 20468644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 204720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2048965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (!mIsAudio) { 2049965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong lastCttsDurTicks = currCttsDurTicks; 2050965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong lastCttsTimeUs = cttsDeltaTimeUs; 2051965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2052965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2053d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 20541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStssTableEntry(mNumSamples); 2055d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 2056d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 205793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 205893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 205993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 206093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 2061faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 206293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 206343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 2064c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 206558ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 206658ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mChunkOffsets.empty()) { 20671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 206858ae9c530247668f8af36e30d228c716c226b3d4James Dong } 206958ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 207058ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 207158ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 207258ae9c530247668f8af36e30d228c716c226b3d4James Dong } 207313aec890216948b0c364f8f92792129d0335f506James Dong 207413aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 207513aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 20761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 20771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 207813aec890216948b0c364f8f92792129d0335f506James Dong } else { 207913aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 208013aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 208113aec890216948b0c364f8f92792129d0335f506James Dong } else { 208243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int64_t chunkDurationUs = timestampUs - chunkTimestampUs; 208343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > interleaveDurationUs) { 208443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (chunkDurationUs > mMaxChunkDurationUs) { 208543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs = chunkDurationUs; 208643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 208713aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 208813aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 208913aec890216948b0c364f8f92792129d0335f506James Dong (--(mStscTableEntries.end()))->samplesPerChunk != 209013aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size()) { 20911f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(nChunks, mChunkSamples.size()); 209213aec890216948b0c364f8f92792129d0335f506James Dong } 20931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 209413aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 209513aec890216948b0c364f8f92792129d0335f506James Dong } 209613aec890216948b0c364f8f92792129d0335f506James Dong } 209713aec890216948b0c364f8f92792129d0335f506James Dong } 209813aec890216948b0c364f8f92792129d0335f506James Dong 209920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 210025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 210145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (isTrackMalFormed()) { 2102690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 2103f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 210445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 2105bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, -1, err); 2106be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 210713aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 210843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (!hasMultipleTracks) { 21091f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(1, mNumSamples); 211058ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 21111f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 21121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 211313aec890216948b0c364f8f92792129d0335f506James Dong } 211413aec890216948b0c364f8f92792129d0335f506James Dong 2115be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 2116be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 2117be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 2118ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples == 1) { 21198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 212079761ab096f57c3027fad9556c2bc436672d614eJames Dong lastDurationTicks = 0; 2121965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong lastCttsDurTicks = 0; 2122be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2123be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 2124965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong ++cttsSampleCount; 2125be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2126a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2127a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (mNumSamples <= 2) { 212879761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(1, lastDurationTicks); 2129a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (sampleCount - 1 > 0) { 213079761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount - 1, lastDurationTicks); 2131a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2132a472613aec322e25891abf5c77bf3f7e3c244920James Dong } else { 213379761ab096f57c3027fad9556c2bc436672d614eJames Dong addOneSttsTableEntry(sampleCount, lastDurationTicks); 2134a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 2135a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2136965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks); 2137c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 213825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 213943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 214043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong sendTrackSummary(hasMultipleTracks); 214143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 21421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 21431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video"); 2144872a481558350634a3fd5cb67939de288af00ecbJames Dong if (mIsAudio) { 2145872a481558350634a3fd5cb67939de288af00ecbJames Dong LOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs()); 2146872a481558350634a3fd5cb67939de288af00ecbJames Dong } 2147365a963142093a1cd8efdcea76b5f65096a5b115James Dong 214837187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 214937187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 215037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 215137187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 2152365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 2153365a963142093a1cd8efdcea76b5f65096a5b115James Dong 215445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dongbool MPEG4Writer::Track::isTrackMalFormed() const { 215545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (mSampleSizes.empty()) { // no samples written 215645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong LOGE("The number of recorded samples is 0"); 215745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 215845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 215945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 216045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (!mIsAudio && mNumStssTableEntries == 0) { // no sync frames for video 216145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong LOGE("There are no sync frames for video track"); 216245c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 216345c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 216445c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 216545c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong if (OK != checkCodecSpecificData()) { // no codec specific data 216645c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return true; 216745c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong } 216845c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 216945c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong return false; 217045c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong} 217145c254c0c535e1d62f23d14cab7385d536c1e2bfJames Dong 217243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dongvoid MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) { 217307ec01904613a0bac32caaa8444b4690998faed7James Dong 217407ec01904613a0bac32caaa8444b4690998faed7James Dong // Send track summary only if test mode is enabled. 217507ec01904613a0bac32caaa8444b4690998faed7James Dong if (!isTestModeEnabled()) { 217607ec01904613a0bac32caaa8444b4690998faed7James Dong return; 217707ec01904613a0bac32caaa8444b4690998faed7James Dong } 217807ec01904613a0bac32caaa8444b4690998faed7James Dong 217943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong int trackNum = (mTrackId << 28); 218043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 218143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 218243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE, 218343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mIsAudio? 0: 1); 218443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 218543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 218643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS, 218743ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mTrackDurationUs / 1000); 218843ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 218943ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 219043ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES, 219143ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mNumSamples); 219243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 219386b7f47aa7482424cf8fd248f1315311919be3b0James Dong { 219486b7f47aa7482424cf8fd248f1315311919be3b0James Dong // The system delay time excluding the requested initial delay that 219586b7f47aa7482424cf8fd248f1315311919be3b0James Dong // is used to eliminate the recording sound. 219686b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL; 219786b7f47aa7482424cf8fd248f1315311919be3b0James Dong if (startTimeOffsetUs < 0) { // Start time offset was not set 219886b7f47aa7482424cf8fd248f1315311919be3b0James Dong startTimeOffsetUs = kInitialDelayTimeUs; 219986b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 220086b7f47aa7482424cf8fd248f1315311919be3b0James Dong int64_t initialDelayUs = 220186b7f47aa7482424cf8fd248f1315311919be3b0James Dong mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs; 220286b7f47aa7482424cf8fd248f1315311919be3b0James Dong 220386b7f47aa7482424cf8fd248f1315311919be3b0James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 220470ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS, 220570ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong (initialDelayUs) / 1000); 220686b7f47aa7482424cf8fd248f1315311919be3b0James Dong } 220770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 220807ec01904613a0bac32caaa8444b4690998faed7James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 220907ec01904613a0bac32caaa8444b4690998faed7James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES, 221007ec01904613a0bac32caaa8444b4690998faed7James Dong mMdatSizeBytes / 1024); 221107ec01904613a0bac32caaa8444b4690998faed7James Dong 221243ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong if (hasMultipleTracks) { 221343ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 221443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS, 221543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong mMaxChunkDurationUs / 1000); 221670ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 221770ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 221870ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong if (mStartTimestampUs != moovStartTimeUs) { 221970ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 222070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 222170ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS, 222270ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong startTimeOffsetUs / 1000); 222370ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong } 222443ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong } 222543ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong} 222643ec1dfc5dc3934680a52a026c5519ddc51bdbd3James Dong 2227faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 2228faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong LOGV("trackProgressStatus: %lld us", timeUs); 2229215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 2230215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 223193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Fire time tracking progress status at %lld us", timeUs); 2232bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err); 223393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 223493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 223593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 223693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 2237faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 2238bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong size_t trackId, int64_t timeUs, status_t err) { 2239faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 2240bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong int32_t trackNum = (trackId << 28); 2241faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2242faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 2243faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 2244faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 2245bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_ERROR, 2246bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, 2247faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2248faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 2249faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2250faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2251faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 2252faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 2253bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2254bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, 2255faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 2256faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 2257faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 2258bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong notify(MEDIA_RECORDER_TRACK_EVENT_INFO, 2259bc07bcc65e91c7aea9713631ae67760dcf1b0286James Dong trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME, 2260faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 2261faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 2262faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 2263faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 2264d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 2265d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong LOGV("setDriftTimeUs: %lld us", driftTimeUs); 2266e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2267d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 2268e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2269e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2270e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 2271e259531ce59ab1f31de5a23124b22536f6a5a767James Dong LOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 2272e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 2273e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 2274e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 2275e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 2276b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 2277b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 2278b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 2279b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 22801c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 22811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("bufferChunk"); 22821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 22831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 22841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 228513aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 228620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 228720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22883b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 2289c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 229020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 229120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2292d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 2293d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 2294d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 2295d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 2296690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 2297690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 2298690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 2299690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 2300690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 2301690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2302690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 2303690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 2304a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong LOGE("Missing codec specific data"); 2305690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2306690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2307690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 2308690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 2309690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 2310a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong LOGE("Unexepected codec specific data found"); 2311690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 2312690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2313690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 2314690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 2315690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 2316690f546b0ee548dbfe997df36418e5302ec2d786James Dong 2317b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) { 231820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("%s track time scale: %d", 23201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 23218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 232220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 2323b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("trak"); 2324b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeTkhdBox(now); 2325b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdia"); 2326b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMdhdBox(now); 2327b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeHdlrBox(); 2328b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("minf"); 2329b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2330b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSmhdBox(); 2331b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2332b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVmhdBox(); 2333b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2334b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDinfBox(); 2335b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStblBox(use32BitOffset); 2336b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // minf 2337b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mdia 2338b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // trak 2339b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2340b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2341b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStblBox(bool use32BitOffset) { 2342b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stbl"); 2343b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsd"); 2344b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2345b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count 2346b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2347b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAudioFourCCBox(); 2348b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2349b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeVideoFourCCBox(); 2350b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2351b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsd 2352b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeSttsBox(); 2353965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong writeCttsBox(); 2354b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mIsAudio) { 2355b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStssBox(); 2356b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2357b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStszBox(); 2358b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStscBox(); 2359b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeStcoBox(use32BitOffset); 2360b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stbl 2361b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2362b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2363b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVideoFourCCBox() { 2364b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2365b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2366b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2367b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2368b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mp4v"); 2369b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2370b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("s263"); 2371b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2372b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avc1"); 2373b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2374b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong LOGE("Unknown mime type '%s'.", mime); 2375b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2376b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2377b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2378b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2379b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2380b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // data ref index 2381b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2382b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2383b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2384b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2385b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // predefined 2386b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2387b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2388b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeyWidth, &width); 2389b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2390b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2391b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2392b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(width); 2393b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(height); 2394b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // horiz resolution 2395b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x480000); // vert resolution 2396b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2397b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(1); // frame count 2398b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(" ", 32); 2399b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x18); // depth 2400b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(-1); // predefined 2401b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2402b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(23 + mCodecSpecificDataSize < 128); 2403b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2404b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2405b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4vEsdsBox(); 2406b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 2407b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeD263Box(); 2408b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 2409b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeAvccBox(); 2410b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2411b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2412b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writePaspBox(); 2413b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // mp4v, s263 or avc1 2414b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2415b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2416b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAudioFourCCBox() { 2417b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *mime; 2418b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findCString(kKeyMIMEType, &mime); 2419b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2420b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong const char *fourcc = NULL; 2421b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 2422b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "samr"; 2423b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2424b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "sawb"; 2425b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2426b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong fourcc = "mp4a"; 2427b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2428b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong LOGE("Unknown mime type '%s'.", mime); 2429b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(!"should not be here, unknown mime type."); 2430b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2431b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2432b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(fourcc); // audio format 2433b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2434b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2435b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x1); // data ref index 2436b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2437b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2438b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t nChannels; 2439b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 2440b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(nChannels); // channel count 2441b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(16); // sample size 2442b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2443b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2444b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2445b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t samplerate; 2446b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = mMeta->findInt32(kKeySampleRate, &samplerate); 2447b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2448b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(samplerate << 16); 2449b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 2450b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeMp4aEsdsBox(); 2451b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 2452b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 2453b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDamrBox(); 2454b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2455b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2456b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2457b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2458b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4aEsdsBox() { 2459b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2460b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 2461b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificDataSize > 0); 2462b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2463b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Make sure all sizes encode to a single byte. 2464b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificDataSize + 23 < 128); 2465b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2466b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2467b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2468b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2469b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000);// ES_ID 2470b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); 2471b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2472b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2473b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2474b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 2475b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x15); // streamType AudioStream 2476b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2477b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x03); // XXX 2478b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2479b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // max bit rate 2480b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(96000); // avg bit rate 2481b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2482b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2483b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2484b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2485b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2486b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2487b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2488b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2489b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2490b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2491b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2492b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2493b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2494b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2495b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2496b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMp4vEsdsBox() { 2497b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 2498b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificDataSize > 0); 2499b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("esds"); 2500b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2501b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2502b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2503b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x03); // ES_DescrTag 2504b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 2505b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x0000); // ES_ID 2506b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x1f); 2507b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2508b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 2509b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 2510b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 2511b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x11); // streamType VisualStream 2512b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2513b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData[] = { 2514b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 0x77, 0x00, 2515b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00, 2516b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x00, 0x03, 0xe8, 0x00 2517b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2518b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData, sizeof(kData)); 2519b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2520b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2521b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2522b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(mCodecSpecificDataSize); 2523b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2524b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2525b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong static const uint8_t kData2[] = { 2526b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x06, // SLConfigDescriptorTag 2527b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x01, 2528b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 0x02 2529b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong }; 2530b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(kData2, sizeof(kData2)); 2531b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2532b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // esds 2533b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2534b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2535b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeTkhdBox(time_t now) { 2536b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("tkhd"); 2537b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Flags = 7 to indicate that the track is enabled, and 2538b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // part of the presentation 2539b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x07); // version=0, flags=7 2540b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2541b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2542b5212db69734962f55e1493d3e696794172ced51James Dong mOwner->writeInt32(mTrackId + 1); // track id starts with 1 2543b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 25448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 2545b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 2546b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t tkhdDuration = 2547b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 2548b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 2549b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2550b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2551b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // layer 2552b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // alternate group 2553b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 2554b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2555b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2556b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCompositionMatrix(mRotation); // matrix 255720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2558b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mIsAudio) { 2559b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2560b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2561b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2562b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t width, height; 2563b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong bool success = mMeta->findInt32(kKeyWidth, &width); 2564b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong success = success && mMeta->findInt32(kKeyHeight, &height); 2565b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(success); 2566b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2567b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 2568b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 2569b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2570b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // tkhd 2571b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2572b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2573b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeVmhdBox() { 2574b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("vmhd"); 2575b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0x01); // version=0, flags=1 2576b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // graphics mode 2577b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // opcolor 2578b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2579b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); 2580b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2581b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2582b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2583b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSmhdBox() { 2584b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("smhd"); 2585b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2586b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // balance 2587b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // reserved 2588b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2589b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2590b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2591b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeHdlrBox() { 2592b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("hdlr"); 2593b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2594b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // component type: should be mhlr 2595b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 2596b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2597b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2598b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // reserved 2599b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Removing "r" for the name string just makes the string 4 byte aligned 2600b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 2601b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2602b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2603b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2604b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeMdhdBox(time_t now) { 2605b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t trakDurationUs = getDurationUs(); 2606b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("mdhd"); 2607b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2608b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // creation time 2609b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(now); // modification time 2610b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mTimeScale); // media timescale 2611b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 2612b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mdhdDuration); // use media timescale 2613b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Language follows the three letter standard ISO-639-2/T 2614b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 'e', 'n', 'g' for "English", for instance. 2615b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Each character is packed as the difference between its ASCII value and 0x60. 2616b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // For "English", these are 00101, 01110, 00111. 2617b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // XXX: Where is the padding bit located: 0x15C7? 2618b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // language code 2619b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0); // predefined 2620b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2621b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2622b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2623b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDamrBox() { 2624b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // 3gpp2 Spec AMRSampleEntry fields 2625b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("damr"); 2626b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeCString(" "); // vendor: 4 bytes 2627b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2628b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 2629b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // mode change period 2630b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(1); // frames per sample 2631b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); 2632b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2633b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2634b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeUrlBox() { 2635b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // The table index here refers to the sample description index 2636b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // in the sample table entries. 2637b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("url "); 2638b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 2639b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // url 2640b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2641b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2642b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDrefBox() { 2643b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dref"); 2644b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2645b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1); // entry count (either url or urn) 2646b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeUrlBox(); 2647b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dref 2648b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2649b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2650b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeDinfBox() { 2651b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("dinf"); 2652b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong writeDrefBox(); 2653b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // dinf 2654b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2655b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2656b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeAvccBox() { 2657b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificData); 2658b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mCodecSpecificDataSize >= 5); 2659b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2660b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // Patch avcc's lengthSize field to match the number 2661b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong // of bytes we use to indicate the size of a nal unit. 2662b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong uint8_t *ptr = (uint8_t *)mCodecSpecificData; 2663b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1); 2664b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("avcC"); 2665b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2666b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // avcC 2667b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2668b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2669b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeD263Box() { 2670b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("d263"); 2671b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // vendor 2672b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // decoder version 2673b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(10); // level: 10 2674b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt8(0); // profile: 0 2675b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // d263 2676b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2677b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2678b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong// This is useful if the pixel is not square 2679b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writePaspBox() { 2680b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("pasp"); 2681b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // hspacing 2682b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(1 << 16); // vspacing 2683b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // pasp 2684b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 2685b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong 2686b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeSttsBox() { 2687b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stts"); 2688b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2689b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mNumSttsTableEntries); 269070ccfd44c4bfe95ddecc2df6c3695efc48229d72James Dong 2691a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Compensate for small start time difference from different media tracks 2692a472613aec322e25891abf5c77bf3f7e3c244920James Dong int64_t trackStartTimeOffsetUs = 0; 2693b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 2694b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mStartTimestampUs != moovStartTimeUs) { 2695b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong CHECK(mStartTimestampUs > moovStartTimeUs); 2696b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs; 2697b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 269879761ab096f57c3027fad9556c2bc436672d614eJames Dong List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 269979761ab096f57c3027fad9556c2bc436672d614eJames Dong CHECK(it != mSttsTableEntries.end() && it->sampleCount == 1); 270079761ab096f57c3027fad9556c2bc436672d614eJames Dong mOwner->writeInt32(it->sampleCount); 270179761ab096f57c3027fad9556c2bc436672d614eJames Dong int32_t dur = (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL; 270279761ab096f57c3027fad9556c2bc436672d614eJames Dong mOwner->writeInt32(dur + it->sampleDuration); 2703a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2704965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t totalCount = 1; 270579761ab096f57c3027fad9556c2bc436672d614eJames Dong while (++it != mSttsTableEntries.end()) { 270679761ab096f57c3027fad9556c2bc436672d614eJames Dong mOwner->writeInt32(it->sampleCount); 270779761ab096f57c3027fad9556c2bc436672d614eJames Dong mOwner->writeInt32(it->sampleDuration); 2708965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong totalCount += it->sampleCount; 2709b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2710965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(totalCount == mNumSamples); 2711b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stts 2712b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 271320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2714965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dongvoid MPEG4Writer::Track::writeCttsBox() { 2715965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mIsAudio) { // ctts is not for audio 2716965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 2717965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2718965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2719965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong // Do not write ctts box when there is no need to have it. 2720965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if ((mNumCttsTableEntries == 1 && 2721965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mCttsTableEntries.begin()->sampleDuration == 0) || 2722965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mNumCttsTableEntries == 0) { 2723965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong return; 2724965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2725965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2726965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong LOGV("ctts box has %d entries", mNumCttsTableEntries); 2727965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2728965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->beginBox("ctts"); 2729965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong if (mHasNegativeCttsDeltaDuration) { 2730965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->writeInt32(0x00010000); // version=1, flags=0 2731965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } else { 2732965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->writeInt32(0); // version=0, flags=0 2733965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2734965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->writeInt32(mNumCttsTableEntries); 2735965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2736965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong int64_t totalCount = 0; 2737965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong for (List<CttsTableEntry>::iterator it = mCttsTableEntries.begin(); 2738965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong it != mCttsTableEntries.end(); ++it) { 2739965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->writeInt32(it->sampleCount); 2740965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->writeInt32(it->sampleDuration); 2741965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong totalCount += it->sampleCount; 2742965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong } 2743965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong CHECK(totalCount == mNumSamples); 2744965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong mOwner->endBox(); // ctts 2745965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong} 2746965e4239ca1cf6c824c1f8ce23116f9ba8cf6ebdJames Dong 2747b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStssBox() { 2748b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stss"); 2749b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2750b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mNumStssTableEntries); // number of sync frames 2751b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<int32_t>::iterator it = mStssTableEntries.begin(); 2752b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mStssTableEntries.end(); ++it) { 2753b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(*it); 2754b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2755b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stss 2756b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 275725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 2758b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStszBox() { 2759b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsz"); 2760b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2761b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (mSamplesHaveSameSize) { 2762b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong List<size_t>::iterator it = mSampleSizes.begin(); 2763b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(*it); // default sample size 2764b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2765b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); 2766b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2767b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mNumSamples); 2768b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (!mSamplesHaveSameSize) { 2769b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<size_t>::iterator it = mSampleSizes.begin(); 2770b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mSampleSizes.end(); ++it) { 2771b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(*it); 2772b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2773b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2774b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsz 2775b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 277620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2777b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStscBox() { 2778b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox("stsc"); 2779b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2780b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mNumStscTableEntries); 2781b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 2782b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mStscTableEntries.end(); ++it) { 2783b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(it->firstChunk); 2784b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(it->samplesPerChunk); 2785b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(it->sampleDescriptionId); 2786b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2787b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stsc 2788b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong} 278920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2790b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dongvoid MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 2791b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 2792b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(0); // version=0, flags=0 2793b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(mNumStcoTableEntries); 2794b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong for (List<off64_t>::iterator it = mChunkOffsets.begin(); 2795b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong it != mChunkOffsets.end(); ++it) { 2796b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong if (use32BitOffset) { 2797b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt32(static_cast<int32_t>(*it)); 2798b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } else { 2799b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->writeInt64((*it)); 2800b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2801b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong } 2802b21c564ce47041f9dd3ab65e36fed57c4937a42dJames Dong mOwner->endBox(); // stco or co64 280320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 280420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 280507b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeUdtaBox() { 280607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("udta"); 280707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeGeoDataBox(); 280807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 280907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 281007b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 281107b1bb529a1ae76c46a71b01338c166f9490629dJames Dong/* 281207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * Geodata is stored according to ISO-6709 standard. 281307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 281407b1bb529a1ae76c46a71b01338c166f9490629dJames Dongvoid MPEG4Writer::writeGeoDataBox() { 281507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong beginBox("\xA9xyz"); 281607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong /* 281707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * For historical reasons, any user data start 281807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * with "\0xA9", must be followed by its assoicated 281907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong * language code. 2820432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x0012: text string length 2821432ec3768cc4a3b1b01afedc456689d75c89ee2bJames Dong * 0x15c7: lang (locale) code: en 282207b1bb529a1ae76c46a71b01338c166f9490629dJames Dong */ 282307b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt32(0x001215c7); 282407b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLatitude(mLatitudex10000); 282507b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeLongitude(mLongitudex10000); 282607b1bb529a1ae76c46a71b01338c166f9490629dJames Dong writeInt8(0x2F); 282707b1bb529a1ae76c46a71b01338c166f9490629dJames Dong endBox(); 282807b1bb529a1ae76c46a71b01338c166f9490629dJames Dong} 282907b1bb529a1ae76c46a71b01338c166f9490629dJames Dong 283020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 2831