MPEG4Writer.cpp revision d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/* 220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project 320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License. 620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at 720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software 1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and 1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License. 1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */ 1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0 18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "MPEG4Writer" 19050b28a593350047845a45a14cc5026221ac1620James Dong#include <utils/Log.h> 20050b28a593350047845a45a14cc5026221ac1620James Dong 2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h> 2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h> 2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <pthread.h> 2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 290c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h> 3018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 3103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber#include <media/stagefright/MediaErrors.h> 3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 34d599cd4573b5a2d5914c5040e0565ef866749b77James Dong#include <media/mediarecorder.h> 3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber#include "include/ESDS.h" 3719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongstatic const int64_t kMax32BitFileSize = 0x007fffffffLL; 413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypeSeqParamSet = 0x07; 423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t kNalUnitTypePicParamSet = 0x08; 433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Writer::Track { 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 4625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track(MPEG4Writer *owner, const sp<MediaSource> &source); 478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ~Track(); 4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t start(MetaData *params); 5137187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t stop(); 5237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t pause(); 5325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool reachedEOS(); 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 553b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber int64_t getDurationUs() const; 56d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t getEstimatedTrackSizeBytes() const; 571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong void writeTrackHeader(int32_t trackID, bool use32BitOffset = true); 581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void bufferChunk(int64_t timestampUs); 591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAvc() const { return mIsAvc; } 601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isAudio() const { return mIsAudio; } 611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool isMPEG4() const { return mIsMPEG4; } 621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addChunkOffset(off_t offset); 63dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong status_t dump(int fd, const Vector<String16>& args) const; 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Writer *mOwner; 6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mMeta; 68693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> mSource; 6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber volatile bool mDone; 70a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mPaused; 71a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong volatile bool mResumed; 721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAvc; 731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsAudio; 741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bool mIsMPEG4; 75c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong int64_t mTrackDurationUs; 76e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 77e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // For realtime applications, we need to adjust the media clock 78e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // for video track based on the audio media clock 79e259531ce59ab1f31de5a23124b22536f6a5a767James Dong bool mIsRealTimeRecording; 80e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int64_t mMaxTimeStampUs; 81d599cd4573b5a2d5914c5040e0565ef866749b77James Dong int64_t mEstimatedTrackSizeBytes; 821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t mMdatSizeBytes; 838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mTimeScale; 8420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_t mThread; 8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 87ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // mNumSamples is used to track how many samples in mSampleSizes List. 88ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // This is to reduce the cost associated with mSampleSizes.size() call, 89ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong // since it is O(n). Ideally, the fix should be in List class. 90ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong size_t mNumSamples; 918644c14618d30d9e57a69df40ed939986ebf02c4James Dong List<size_t> mSampleSizes; 92be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong bool mSamplesHaveSameSize; 93be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 9413aec890216948b0c364f8f92792129d0335f506James Dong List<MediaBuffer *> mChunkSamples; 951f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 961f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStcoTableEntries; 9713aec890216948b0c364f8f92792129d0335f506James Dong List<off_t> mChunkOffsets; 9813aec890216948b0c364f8f92792129d0335f506James Dong 991f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStscTableEntries; 10013aec890216948b0c364f8f92792129d0335f506James Dong struct StscTableEntry { 10113aec890216948b0c364f8f92792129d0335f506James Dong 10213aec890216948b0c364f8f92792129d0335f506James Dong StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 10313aec890216948b0c364f8f92792129d0335f506James Dong : firstChunk(chunk), 10413aec890216948b0c364f8f92792129d0335f506James Dong samplesPerChunk(samples), 10513aec890216948b0c364f8f92792129d0335f506James Dong sampleDescriptionId(id) {} 10613aec890216948b0c364f8f92792129d0335f506James Dong 10713aec890216948b0c364f8f92792129d0335f506James Dong uint32_t firstChunk; 10813aec890216948b0c364f8f92792129d0335f506James Dong uint32_t samplesPerChunk; 10913aec890216948b0c364f8f92792129d0335f506James Dong uint32_t sampleDescriptionId; 11013aec890216948b0c364f8f92792129d0335f506James Dong }; 11113aec890216948b0c364f8f92792129d0335f506James Dong List<StscTableEntry> mStscTableEntries; 11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1131f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumStssTableEntries; 114050b28a593350047845a45a14cc5026221ac1620James Dong List<int32_t> mStssTableEntries; 115050b28a593350047845a45a14cc5026221ac1620James Dong 1161f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t mNumSttsTableEntries; 117be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong struct SttsTableEntry { 118be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 1198f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong SttsTableEntry(uint32_t count, uint32_t durationUs) 1208f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong : sampleCount(count), sampleDurationUs(durationUs) {} 121be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 122be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t sampleCount; 1238f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong uint32_t sampleDurationUs; 124be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong }; 125be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong List<SttsTableEntry> mSttsTableEntries; 126be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 1273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Sequence parameter set or picture parameter set 1283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong struct AVCParamSet { 1293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet(uint16_t length, const uint8_t *data) 1303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong : mLength(length), mData(data) {} 1313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 1323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t mLength; 1333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *mData; 1343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong }; 1353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mSeqParamSets; 1363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong List<AVCParamSet> mPicParamSets; 1373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileIdc; 1383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mProfileCompatible; 1393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t mLevelIdc; 1403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *mCodecSpecificData; 14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mCodecSpecificDataSize; 143548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber bool mGotAllCodecSpecificData; 14493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong bool mTrackingProgressStatus; 14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool mReachedEOS; 1473c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong int64_t mStartTimestampUs; 14893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mPreviousTrackTimeUs; 14993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t mTrackEveryTimeDurationUs; 15025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static void *ThreadWrapper(void *me); 15237187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t threadEntry(); 15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *parseParamSet( 1553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen); 1563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 15703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t makeAVCCodecSpecificData( 15803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size); 1593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong status_t copyAVCCodecSpecificData( 1603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size); 1613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong status_t parseAVCCodecSpecificData( 1623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size); 163215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong 164215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong // Track authoring progress status 165faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong void trackProgressStatus(int64_t timeUs, status_t err = OK); 16693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong void initTrackingProgressStatus(MetaData *params); 16703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 16819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber void getCodecSpecificDataFromInputFormatIfPossible(); 16919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 170c059860c73678a202bfa33062723e8f82fb779d9James Dong // Determine the track time scale 171c059860c73678a202bfa33062723e8f82fb779d9James Dong // If it is an audio track, try to use the sampling rate as 172c059860c73678a202bfa33062723e8f82fb779d9James Dong // the time scale; however, if user chooses the overwrite 173c059860c73678a202bfa33062723e8f82fb779d9James Dong // value, the user-supplied time scale will be used. 174c059860c73678a202bfa33062723e8f82fb779d9James Dong void setTimeScale(); 175c059860c73678a202bfa33062723e8f82fb779d9James Dong 176690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Simple validation on the codec specific data 177690f546b0ee548dbfe997df36418e5302ec2d786James Dong status_t checkCodecSpecificData() const; 178690f546b0ee548dbfe997df36418e5302ec2d786James Dong 1791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void updateTrackSizeEstimate(); 1801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStscTableEntry(size_t chunkId, size_t sampleId); 1811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneStssTableEntry(size_t sampleId); 1821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong void addOneSttsTableEntry(size_t sampleCount, int64_t durationUs); 1831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track(const Track &); 18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track &operator=(const Track &); 18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::MPEG4Writer(const char *filename) 18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFile(fopen(filename, "wb")), 190b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 1911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 192a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 193a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset(0), 19513aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 1967837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 197f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong mInterleaveDurationUs(1000000) { 1980c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mFile != NULL); 19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20130ab66297501757d745b9ae10da61adcd891f497Andreas HuberMPEG4Writer::MPEG4Writer(int fd) 20230ab66297501757d745b9ae10da61adcd891f497Andreas Huber : mFile(fdopen(fd, "wb")), 203b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength(true), 2041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mUse32BitOffset(true), 205a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 206a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted(false), 20730ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOffset(0), 20813aec890216948b0c364f8f92792129d0335f506James Dong mMdatOffset(0), 2097837c17063a4c50bc856ba59418516fdab731de7James Dong mEstimatedMoovBoxSize(0), 210f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong mInterleaveDurationUs(1000000) { 21130ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK(mFile != NULL); 21230ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 21330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 21420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::~MPEG4Writer() { 21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2171f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong while (!mTracks.empty()) { 2181f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong List<Track *>::iterator it = mTracks.begin(); 21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete *it; 2201f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong (*it) = NULL; 2211f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mTracks.erase(it); 22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.clear(); 22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 226dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::dump( 227dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) { 228dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 229dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 230dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 231dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " MPEG4Writer %p\n", this); 232dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 233dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false"); 234dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 235dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 236dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong for (List<Track *>::iterator it = mTracks.begin(); 237dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong it != mTracks.end(); ++it) { 238dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong (*it)->dump(fd, args); 239dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong } 240dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 241dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 242dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 243dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dongstatus_t MPEG4Writer::Track::dump( 244dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong int fd, const Vector<String16>& args) const { 245dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong const size_t SIZE = 256; 246dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong char buffer[SIZE]; 247dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong String8 result; 248dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video"); 249dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 250dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong snprintf(buffer, SIZE, " reached EOS: %s\n", 251dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong mReachedEOS? "true": "false"); 252dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong result.append(buffer); 253dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong ::write(fd, result.string(), result.size()); 254dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong return OK; 255dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong} 256dedf414d3fe2e79ee0aad0f1c82ca16ebd886ff6James Dong 2572dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 25825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber Track *track = new Track(this, source); 25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mTracks.push_back(track); 2602dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 2612dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::startTracks(MetaData *params) { 265a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 266a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 26793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = (*it)->start(params); 268a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 269a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 270a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it2 = mTracks.begin(); 271a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it2 != it; ++it2) { 272a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong (*it2)->stop(); 273a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 274a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 275a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 276a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 277a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 278a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 279a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 280a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 2812dec2b5be2056c6d9428897dc672185872d30d17James Dongint64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) { 2822dec2b5be2056c6d9428897dc672185872d30d17James Dong // This implementation is highly experimental/heurisitic. 2832dec2b5be2056c6d9428897dc672185872d30d17James Dong // 2842dec2b5be2056c6d9428897dc672185872d30d17James Dong // Statistical analysis shows that metadata usually accounts 2852dec2b5be2056c6d9428897dc672185872d30d17James Dong // for a small portion of the total file size, usually < 0.6%. 2862dec2b5be2056c6d9428897dc672185872d30d17James Dong // Currently, lets set to 0.4% for now. 2872dec2b5be2056c6d9428897dc672185872d30d17James Dong 2882dec2b5be2056c6d9428897dc672185872d30d17James Dong // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB, 2892dec2b5be2056c6d9428897dc672185872d30d17James Dong // where 1MB is the common file size limit for MMS application. 2902dec2b5be2056c6d9428897dc672185872d30d17James Dong // The default MAX _MOOV_BOX_SIZE value is based on about 4 2912dec2b5be2056c6d9428897dc672185872d30d17James Dong // minute video recording with a bit rate about 3 Mbps, because 2922dec2b5be2056c6d9428897dc672185872d30d17James Dong // statistics also show that most of the video captured are going 2932dec2b5be2056c6d9428897dc672185872d30d17James Dong // to be less than 3 minutes. 2942dec2b5be2056c6d9428897dc672185872d30d17James Dong 2952dec2b5be2056c6d9428897dc672185872d30d17James Dong // If the estimation is wrong, we will pay the price of wasting 2962dec2b5be2056c6d9428897dc672185872d30d17James Dong // some reserved space. This should not happen so often statistically. 2972dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int32_t factor = mUse32BitOffset? 1: 2; 2982dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024; // 4 KB 2992dec2b5be2056c6d9428897dc672185872d30d17James Dong static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000); 3002dec2b5be2056c6d9428897dc672185872d30d17James Dong int64_t size = MIN_MOOV_BOX_SIZE; 3012dec2b5be2056c6d9428897dc672185872d30d17James Dong 3022dec2b5be2056c6d9428897dc672185872d30d17James Dong if (mMaxFileSizeLimitBytes != 0) { 3032dec2b5be2056c6d9428897dc672185872d30d17James Dong size = mMaxFileSizeLimitBytes * 4 / 1000; 3042dec2b5be2056c6d9428897dc672185872d30d17James Dong } else if (mMaxFileDurationLimitUs != 0) { 3052dec2b5be2056c6d9428897dc672185872d30d17James Dong if (bitRate <= 0) { 3062dec2b5be2056c6d9428897dc672185872d30d17James Dong // We could not estimate the file size since bitRate is not set. 3072dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 3082dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 3092dec2b5be2056c6d9428897dc672185872d30d17James Dong size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000); 3102dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3112dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3122dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size < MIN_MOOV_BOX_SIZE) { 3132dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MIN_MOOV_BOX_SIZE; 3142dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3152dec2b5be2056c6d9428897dc672185872d30d17James Dong 3162dec2b5be2056c6d9428897dc672185872d30d17James Dong // Any long duration recording will be probably end up with 3172dec2b5be2056c6d9428897dc672185872d30d17James Dong // non-streamable mp4 file. 3182dec2b5be2056c6d9428897dc672185872d30d17James Dong if (size > MAX_MOOV_BOX_SIZE) { 3192dec2b5be2056c6d9428897dc672185872d30d17James Dong size = MAX_MOOV_BOX_SIZE; 3202dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3212dec2b5be2056c6d9428897dc672185872d30d17James Dong 3222dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated" 3232dec2b5be2056c6d9428897dc672185872d30d17James Dong " moov size %lld bytes", 3242dec2b5be2056c6d9428897dc672185872d30d17James Dong mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size); 3252dec2b5be2056c6d9428897dc672185872d30d17James Dong return factor * size; 3262dec2b5be2056c6d9428897dc672185872d30d17James Dong} 3272dec2b5be2056c6d9428897dc672185872d30d17James Dong 3282dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t MPEG4Writer::start(MetaData *param) { 32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 33025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return UNKNOWN_ERROR; 33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3332dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t use64BitOffset; 3342dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param && 3352dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKey64BitFileOffset, &use64BitOffset) && 3362dec2b5be2056c6d9428897dc672185872d30d17James Dong use64BitOffset) { 3372dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse32BitOffset = false; 3382dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3392dec2b5be2056c6d9428897dc672185872d30d17James Dong 3401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mUse32BitOffset) { 3411f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // Implicit 32 bit file size limit 3421f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes == 0) { 3431f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 3441f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 3451f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 3461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // If file size is set to be larger than the 32 bit file 3471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong // size limit, treat it as an error. 3481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong if (mMaxFileSizeLimitBytes > kMax32BitFileSize) { 349d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong LOGW("32-bi file size limit (%lld bytes) too big. " 350d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong "It is changed to %lld bytes", 351d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes, kMax32BitFileSize); 352d2518e0c0a5bffd30b0dccb04fe7bf5b77c354b1James Dong mMaxFileSizeLimitBytes = kMax32BitFileSize; 3531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 3541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong } 3551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 356b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong int32_t use2ByteNalLength; 357b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (param && 358b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) && 359b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong use2ByteNalLength) { 360b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mUse4ByteNalLength = false; 3612dec2b5be2056c6d9428897dc672185872d30d17James Dong } 3622dec2b5be2056c6d9428897dc672185872d30d17James Dong 363065d1aff96818df54456053f1574aec8a234d0deJames Dong mStartTimestampUs = -1; 36493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 365a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mStarted) { 366a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused) { 367a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 36893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return startTracks(param); 369a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 370a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 371a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 372a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 3738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (!param || 3748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong !param->findInt32(kKeyTimeScale, &mTimeScale)) { 3758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mTimeScale = 1000; 3768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 3778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 3788f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("movie time scale: %d", mTimeScale); 3798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 3807837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = true; 3817837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 3827837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 3837837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 3847837c17063a4c50bc856ba59418516fdab731de7James Dong 38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("ftyp"); 38693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 38793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t fileType; 38893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (param && param->findInt32(kKeyFileType, &fileType) && 38993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong fileType != OUTPUT_FORMAT_MPEG_4) { 39093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("3gp4"); 39193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } else { 39293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("isom"); 39393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 39493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc("isom"); 39793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong writeFourcc("3gp4"); 39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); 39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4007837c17063a4c50bc856ba59418516fdab731de7James Dong mFreeBoxOffset = mOffset; 40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4027837c17063a4c50bc856ba59418516fdab731de7James Dong if (mEstimatedMoovBoxSize == 0) { 4032dec2b5be2056c6d9428897dc672185872d30d17James Dong int32_t bitRate = -1; 4042dec2b5be2056c6d9428897dc672185872d30d17James Dong if (param) { 4052dec2b5be2056c6d9428897dc672185872d30d17James Dong param->findInt32(kKeyBitRate, &bitRate); 4062dec2b5be2056c6d9428897dc672185872d30d17James Dong } 4072dec2b5be2056c6d9428897dc672185872d30d17James Dong mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate); 4087837c17063a4c50bc856ba59418516fdab731de7James Dong } 4097837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mEstimatedMoovBoxSize >= 8); 4107837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 4117837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize); 4127837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 4137837c17063a4c50bc856ba59418516fdab731de7James Dong 4147837c17063a4c50bc856ba59418516fdab731de7James Dong mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 4157837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mMdatOffset; 4167837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 4171acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 4181acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("????mdat", 8); 4191acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 4201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong write("\x00\x00\x00\x01mdat????????", 16); 4211acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 4221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong status_t err = startWriterThread(); 4241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (err != OK) { 4251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return err; 4261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 4271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong err = startTracks(param); 429a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (err != OK) { 430a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return err; 43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 4321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 433a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = true; 43425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4371f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongbool MPEG4Writer::use32BitFileOffset() const { 4381f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return mUse32BitOffset; 4391f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 4401f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 44137187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::pause() { 442a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mFile == NULL) { 44337187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 444a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 445a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 44637187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 447a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong for (List<Track *>::iterator it = mTracks.begin(); 448a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong it != mTracks.end(); ++it) { 44937187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->pause(); 45037187916a486504acaf83bea30147eb5fbf46ae5James Dong if (status != OK) { 45137187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 45237187916a486504acaf83bea30147eb5fbf46ae5James Dong } 453a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 45437187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 455a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 456a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 4571c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::stopWriterThread() { 4581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("stopWriterThread"); 4591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 4611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 4621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = true; 4641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 4651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 4661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 4671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong void *dummy; 4681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_join(mThread, &dummy); 4691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 4701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 47137187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::stop() { 47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mFile == NULL) { 47337187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 47637187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 4778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t maxDurationUs = 0; 47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it) { 48037187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = (*it)->stop(); 48137187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK) { 48237187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 48337187916a486504acaf83bea30147eb5fbf46ae5James Dong } 48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t durationUs = (*it)->getDurationUs(); 4868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (durationUs > maxDurationUs) { 4878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong maxDurationUs = durationUs; 48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 48920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong stopWriterThread(); 4927837c17063a4c50bc856ba59418516fdab731de7James Dong 49337187916a486504acaf83bea30147eb5fbf46ae5James Dong // Do not write out movie header on error. 49437187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err != OK) { 49537187916a486504acaf83bea30147eb5fbf46ae5James Dong fflush(mFile); 49637187916a486504acaf83bea30147eb5fbf46ae5James Dong fclose(mFile); 49737187916a486504acaf83bea30147eb5fbf46ae5James Dong mFile = NULL; 49837187916a486504acaf83bea30147eb5fbf46ae5James Dong mStarted = false; 49937187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 50037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 50137187916a486504acaf83bea30147eb5fbf46ae5James Dong 50220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Fix up the size of the 'mdat' chunk. 5031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (mUse32BitOffset) { 5041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fseeko(mFile, mMdatOffset, SEEK_SET); 5051acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); 5061acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fwrite(&size, 1, 4, mFile); 5071acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 5081acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fseeko(mFile, mMdatOffset + 8, SEEK_SET); 5091acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int64_t size = mOffset - mMdatOffset; 5101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong size = hton64(size); 5111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong fwrite(&size, 1, 8, mFile); 5121acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 5137837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 5167837c17063a4c50bc856ba59418516fdab731de7James Dong const off_t moovOffset = mOffset; 5177837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = true; 5187837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 5197837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 5207837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBuffer != NULL); 521c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6; 52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("moov"); 52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber beginBox("mvhd"); 52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // version=0, flags=0 52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // creation time 52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(now); // modification time 5298f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong writeInt32(mTimeScale); // mvhd timescale 5301acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(duration); 5311acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong writeInt32(0x10000); // rate: 1.0 53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0x100); // volume 53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt16(0); // reserved 53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // reserved 53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); // matrix 53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x10000); 54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0x40000000); 54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 54620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); // predefined 55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(mTracks.size() + 1); // nextTrackID 55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // mvhd 55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t id = 1; 55520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber it != mTracks.end(); ++it, ++id) { 5571acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong (*it)->writeTrackHeader(id, mUse32BitOffset); 55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber endBox(); // moov 56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5617837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 5627837c17063a4c50bc856ba59418516fdab731de7James Dong if (mStreamableFile) { 5637837c17063a4c50bc856ba59418516fdab731de7James Dong CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 5647837c17063a4c50bc856ba59418516fdab731de7James Dong 5657837c17063a4c50bc856ba59418516fdab731de7James Dong // Moov box 5667837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mFreeBoxOffset, SEEK_SET); 5677837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset = mFreeBoxOffset; 5687837c17063a4c50bc856ba59418516fdab731de7James Dong write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); 5697837c17063a4c50bc856ba59418516fdab731de7James Dong 5707837c17063a4c50bc856ba59418516fdab731de7James Dong // Free box 5712dec2b5be2056c6d9428897dc672185872d30d17James Dong fseeko(mFile, mOffset, SEEK_SET); 5727837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 5737837c17063a4c50bc856ba59418516fdab731de7James Dong write("free", 4); 5747837c17063a4c50bc856ba59418516fdab731de7James Dong 5757837c17063a4c50bc856ba59418516fdab731de7James Dong // Free temp memory 5767837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 5777837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 5787837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 5792dec2b5be2056c6d9428897dc672185872d30d17James Dong } else { 5802dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGI("The mp4 file will not be streamable."); 5817837c17063a4c50bc856ba59418516fdab731de7James Dong } 5827837c17063a4c50bc856ba59418516fdab731de7James Dong 5830c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(mBoxes.empty()); 58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5857837c17063a4c50bc856ba59418516fdab731de7James Dong fflush(mFile); 58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fclose(mFile); 58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFile = NULL; 588a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mStarted = false; 58937187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59213aec890216948b0c364f8f92792129d0335f506James Dongstatus_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 59313aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 59413aec890216948b0c364f8f92792129d0335f506James Dong return OK; 59513aec890216948b0c364f8f92792129d0335f506James Dong} 59613aec890216948b0c364f8f92792129d0335f506James Dong 59713aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::lock() { 59813aec890216948b0c364f8f92792129d0335f506James Dong mLock.lock(); 59913aec890216948b0c364f8f92792129d0335f506James Dong} 60013aec890216948b0c364f8f92792129d0335f506James Dong 60113aec890216948b0c364f8f92792129d0335f506James Dongvoid MPEG4Writer::unlock() { 60213aec890216948b0c364f8f92792129d0335f506James Dong mLock.unlock(); 60313aec890216948b0c364f8f92792129d0335f506James Dong} 60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60513aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t old_offset = mOffset; 60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 60920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1, buffer->range_length(), mFile); 61020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOffset += buffer->range_length(); 61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return old_offset; 61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 61603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) { 61703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->range_length() < 4) { 61803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return; 61903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 62003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 62103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *ptr = 62203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 62303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 62403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 62503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->set_range( 62603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_offset() + 4, buffer->range_length() - 4); 62703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 62803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 62903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 63013aec890216948b0c364f8f92792129d0335f506James Dongoff_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 63130ab66297501757d745b9ae10da61adcd891f497Andreas Huber off_t old_offset = mOffset; 63230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 63330ab66297501757d745b9ae10da61adcd891f497Andreas Huber size_t length = buffer->range_length(); 63403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 635b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mUse4ByteNalLength) { 636b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 24; 637b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite(&x, 1, 1, mFile); 638b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 16) & 0xff; 639b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite(&x, 1, 1, mFile); 640b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = (length >> 8) & 0xff; 641b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite(&x, 1, 1, mFile); 642b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 643b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite(&x, 1, 1, mFile); 644b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 645b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 646b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1, length, mFile); 647b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 4; 648b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 649b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong CHECK(length < 65536); 65030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 651b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong uint8_t x = length >> 8; 652b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite(&x, 1, 1, mFile); 653b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong x = length & 0xff; 654b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite(&x, 1, 1, mFile); 655b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 656b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 1, length, mFile); 657b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong mOffset += length + 2; 658b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 65930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 66030ab66297501757d745b9ae10da61adcd891f497Andreas Huber return old_offset; 66130ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 66230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 6637837c17063a4c50bc856ba59418516fdab731de7James Dongsize_t MPEG4Writer::write( 6647837c17063a4c50bc856ba59418516fdab731de7James Dong const void *ptr, size_t size, size_t nmemb, FILE *stream) { 6657837c17063a4c50bc856ba59418516fdab731de7James Dong 6667837c17063a4c50bc856ba59418516fdab731de7James Dong const size_t bytes = size * nmemb; 6677837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 6681acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; 6691acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (moovBoxSize > mEstimatedMoovBoxSize) { 6707837c17063a4c50bc856ba59418516fdab731de7James Dong for (List<off_t>::iterator it = mBoxes.begin(); 6717837c17063a4c50bc856ba59418516fdab731de7James Dong it != mBoxes.end(); ++it) { 6727837c17063a4c50bc856ba59418516fdab731de7James Dong (*it) += mOffset; 6737837c17063a4c50bc856ba59418516fdab731de7James Dong } 6747837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 6757837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); 6767837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 6777837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += (bytes + mMoovBoxBufferOffset); 6787837c17063a4c50bc856ba59418516fdab731de7James Dong free(mMoovBoxBuffer); 6797837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBuffer = NULL; 6807837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset = 0; 6817837c17063a4c50bc856ba59418516fdab731de7James Dong mWriteMoovBoxToMemory = false; 6827837c17063a4c50bc856ba59418516fdab731de7James Dong mStreamableFile = false; 6837837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 6847837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 6857837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset += bytes; 6867837c17063a4c50bc856ba59418516fdab731de7James Dong } 6877837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 6887837c17063a4c50bc856ba59418516fdab731de7James Dong fwrite(ptr, size, nmemb, stream); 6897837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset += bytes; 6907837c17063a4c50bc856ba59418516fdab731de7James Dong } 6917837c17063a4c50bc856ba59418516fdab731de7James Dong return bytes; 6927837c17063a4c50bc856ba59418516fdab731de7James Dong} 6937837c17063a4c50bc856ba59418516fdab731de7James Dong 69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::beginBox(const char *fourcc) { 6950c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(fourcc), 4); 69620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6977837c17063a4c50bc856ba59418516fdab731de7James Dong mBoxes.push_back(mWriteMoovBoxToMemory? 6987837c17063a4c50bc856ba59418516fdab731de7James Dong mMoovBoxBufferOffset: mOffset); 69920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeInt32(0); 70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber writeFourcc(fourcc); 70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::endBox() { 7050c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mBoxes.empty()); 70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset = *--mBoxes.end(); 70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBoxes.erase(--mBoxes.end()); 70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7107837c17063a4c50bc856ba59418516fdab731de7James Dong if (mWriteMoovBoxToMemory) { 7117837c17063a4c50bc856ba59418516fdab731de7James Dong int32_t x = htonl(mMoovBoxBufferOffset - offset); 7127837c17063a4c50bc856ba59418516fdab731de7James Dong memcpy(mMoovBoxBuffer + offset, &x, 4); 7137837c17063a4c50bc856ba59418516fdab731de7James Dong } else { 7147837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, offset, SEEK_SET); 7157837c17063a4c50bc856ba59418516fdab731de7James Dong writeInt32(mOffset - offset); 7167837c17063a4c50bc856ba59418516fdab731de7James Dong mOffset -= 4; 7177837c17063a4c50bc856ba59418516fdab731de7James Dong fseeko(mFile, mOffset, SEEK_SET); 7187837c17063a4c50bc856ba59418516fdab731de7James Dong } 71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 72020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 72120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt8(int8_t x) { 7227837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 1, mFile); 72320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt16(int16_t x) { 72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htons(x); 7277837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 2, mFile); 72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt32(int32_t x) { 73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = htonl(x); 7327837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 4, mFile); 73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeInt64(int64_t x) { 73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber x = hton64(x); 7377837c17063a4c50bc856ba59418516fdab731de7James Dong write(&x, 1, 8, mFile); 73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeCString(const char *s) { 74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = strlen(s); 7427837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, n + 1, mFile); 74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::writeFourcc(const char *s) { 7460c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK_EQ(strlen(s), 4); 7477837c17063a4c50bc856ba59418516fdab731de7James Dong write(s, 1, 4, mFile); 74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MPEG4Writer::write(const void *data, size_t size) { 7517837c17063a4c50bc856ba59418516fdab731de7James Dong write(data, 1, size, mFile); 75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 754d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileSizeLimit() { 755d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 756d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeLimitBytes == 0) { 757d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 758d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 759d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 760956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize); 761d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 762d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 763d599cd4573b5a2d5914c5040e0565ef866749b77James Dong nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); 764d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 7651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 7661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong return (nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes); 767d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 768d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 769d599cd4573b5a2d5914c5040e0565ef866749b77James Dongbool MPEG4Writer::exceedsFileDurationLimit() { 770d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // No limit 771d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationLimitUs == 0) { 772d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 773d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 774d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 775d599cd4573b5a2d5914c5040e0565ef866749b77James Dong for (List<Track *>::iterator it = mTracks.begin(); 776d599cd4573b5a2d5914c5040e0565ef866749b77James Dong it != mTracks.end(); ++it) { 777d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { 778d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return true; 779d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 780d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 781d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return false; 782d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 783d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 78425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::reachedEOS() { 78525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber bool allDone = true; 78625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber for (List<Track *>::iterator it = mTracks.begin(); 78725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber it != mTracks.end(); ++it) { 78825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (!(*it)->reachedEOS()) { 78925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber allDone = false; 79025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber break; 79125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 79225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 79325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 79425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return allDone; 79525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 79625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 797f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid MPEG4Writer::setStartTimestampUs(int64_t timeUs) { 798f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("setStartTimestampUs: %lld", timeUs); 799f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong CHECK(timeUs >= 0); 8003c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 801065d1aff96818df54456053f1574aec8a234d0deJames Dong if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) { 802f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timeUs; 803f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGI("Earliest track starting time: %lld", mStartTimestampUs); 8043c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 8053c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 8063c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 807f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongint64_t MPEG4Writer::getStartTimestampUs() { 8083c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong Mutex::Autolock autoLock(mLock); 8093c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong return mStartTimestampUs; 8103c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong} 8113c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 81258ae9c530247668f8af36e30d228c716c226b3d4James Dongsize_t MPEG4Writer::numTracks() { 81358ae9c530247668f8af36e30d228c716c226b3d4James Dong Mutex::Autolock autolock(mLock); 81458ae9c530247668f8af36e30d228c716c226b3d4James Dong return mTracks.size(); 81558ae9c530247668f8af36e30d228c716c226b3d4James Dong} 81658ae9c530247668f8af36e30d228c716c226b3d4James Dong 81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::Track( 82025b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber MPEG4Writer *owner, const sp<MediaSource> &source) 82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mOwner(owner), 82225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mMeta(source->getFormat()), 82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSource(source), 82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone(false), 825a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused(false), 826a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed(false), 827c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs(0), 828956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes(0), 829be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize(true), 83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData(NULL), 83125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mCodecSpecificDataSize(0), 832548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData(false), 83325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS(false) { 83419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber getCodecSpecificDataFromInputFormatIfPossible(); 8358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 8361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong const char *mime; 8371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mMeta->findCString(kKeyMIMEType, &mime); 8381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 8391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio = !strncasecmp(mime, "audio/", 6); 8401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 8411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 8421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 843c059860c73678a202bfa33062723e8f82fb779d9James Dong setTimeScale(); 844c059860c73678a202bfa33062723e8f82fb779d9James Dong} 845c059860c73678a202bfa33062723e8f82fb779d9James Dong 8461f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::updateTrackSizeEstimate() { 8471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset() 8491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ? mNumStcoTableEntries * 4 8501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong : mNumStcoTableEntries * 8; 8511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8521f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4); 8531f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8541f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mEstimatedTrackSizeBytes = mMdatSizeBytes + // media data size 8551f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStscTableEntries * 12 + // stsc box size 8561f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStssTableEntries * 4 + // stss box size 8571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumSttsTableEntries * 8 + // stts box size 8581f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong stcoBoxSizeBytes + // stco box size 8591f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong stszBoxSizeBytes; // stsz box size 8601f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8611f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8621f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStscTableEntry( 8631f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t chunkId, size_t sampleId) { 8641f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8651f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong StscTableEntry stscEntry(chunkId, sampleId, 1); 8661f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mStscTableEntries.push_back(stscEntry); 8671f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStscTableEntries; 8681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8691f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8701f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) { 8711f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mStssTableEntries.push_back(sampleId); 8721f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStssTableEntries; 8731f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8741f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8751f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addOneSttsTableEntry( 8761f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong size_t sampleCount, int64_t durationUs) { 8771f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong SttsTableEntry sttsEntry(sampleCount, durationUs); 8791f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mSttsTableEntries.push_back(sttsEntry); 8801f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumSttsTableEntries; 8811f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8821f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 8831f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dongvoid MPEG4Writer::Track::addChunkOffset(off_t offset) { 8841f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong ++mNumStcoTableEntries; 8851f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mChunkOffsets.push_back(offset); 8861f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong} 8871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 888c059860c73678a202bfa33062723e8f82fb779d9James Dongvoid MPEG4Writer::Track::setTimeScale() { 889c059860c73678a202bfa33062723e8f82fb779d9James Dong LOGV("setTimeScale"); 890c059860c73678a202bfa33062723e8f82fb779d9James Dong // Default time scale 891c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = 90000; 892c059860c73678a202bfa33062723e8f82fb779d9James Dong 893c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mIsAudio) { 894c059860c73678a202bfa33062723e8f82fb779d9James Dong // Use the sampling rate as the default time scale for audio track. 895c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t sampleRate; 896c059860c73678a202bfa33062723e8f82fb779d9James Dong bool success = mMeta->findInt32(kKeySampleRate, &sampleRate); 897c059860c73678a202bfa33062723e8f82fb779d9James Dong CHECK(success); 898c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = sampleRate; 899c059860c73678a202bfa33062723e8f82fb779d9James Dong } 900c059860c73678a202bfa33062723e8f82fb779d9James Dong 901c059860c73678a202bfa33062723e8f82fb779d9James Dong // If someone would like to overwrite the timescale, use user-supplied value. 902c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t timeScale; 903c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMeta->findInt32(kKeyTimeScale, &timeScale)) { 904c059860c73678a202bfa33062723e8f82fb779d9James Dong mTimeScale = timeScale; 905c059860c73678a202bfa33062723e8f82fb779d9James Dong } 906c059860c73678a202bfa33062723e8f82fb779d9James Dong 9078f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong CHECK(mTimeScale > 0); 90819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber} 90919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 91019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Hubervoid MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() { 91119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const char *mime; 91219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 91319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 91419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 91519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 91619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 91719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 91819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyAVCC, &type, &data, &size)) { 91919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 92019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 92119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 92219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 92319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 92419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 92519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 92619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber uint32_t type; 92719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber const void *data; 92819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber size_t size; 92919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (mMeta->findData(kKeyESDS, &type, &data, &size)) { 93019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber ESDS esds(data, size); 93119c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (esds.getCodecSpecificInfo(&data, &size) == OK) { 93219c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificData = malloc(size); 93319c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mCodecSpecificDataSize = size; 93419c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber memcpy(mCodecSpecificData, data, size); 93519c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber mGotAllCodecSpecificData = true; 93619c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 93719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 93819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 93920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 94120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Writer::Track::~Track() { 94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 94420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mCodecSpecificData != NULL) { 94520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber free(mCodecSpecificData); 94620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCodecSpecificData = NULL; 94720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 94820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongvoid MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) { 95193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("initTrackingProgressStatus"); 95293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = -1; 95393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = false; 95493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 95593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong { 95693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeUs; 95793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) { 95893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Receive request to track progress status for every %lld us", timeUs); 95993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeUs; 96093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackingProgressStatus = true; 96193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 96293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 96393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 96493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 9651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong// static 9661c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid *MPEG4Writer::ThreadWrapper(void *me) { 9671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("ThreadWrapper: %p", me); 9681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong MPEG4Writer *writer = static_cast<MPEG4Writer *>(me); 9691c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writer->threadFunc(); 9701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return NULL; 9711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 9721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9731c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::bufferChunk(const Chunk& chunk) { 9741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("bufferChunk: %p", chunk.mTrack); 9751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 9761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(mDone, false); 9771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 9791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 9801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunk.mTrack == it->mTrack) { // Found owner 9821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mChunks.push_back(chunk); 9831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.signal(); 9841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return; 9851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 9861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 9871c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK("Received a chunk for a unknown track" == 0); 9891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 9901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9911c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeFirstChunk(ChunkInfo* info) { 9921c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("writeFirstChunk: %p", info->mTrack); 9931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = info->mChunks.begin(); 9951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); 9961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != chunkIt->mSamples.end(); ++it) { 9971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 9981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong off_t offset = info->mTrack->isAvc() 9991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ? addLengthPrefixedSample_l(*it) 10001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong : addSample_l(*it); 10011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it == chunkIt->mSamples.begin()) { 10021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info->mTrack->addChunkOffset(offset); 10031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Done with the current chunk. 10071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Release all the samples in this chunk. 10081c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!chunkIt->mSamples.empty()) { 10091c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); 10101c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it)->release(); 10111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong (*it) = NULL; 10121c9747a4653aec1395c2bd6896c9b87cb5447837James Dong chunkIt->mSamples.erase(it); 10131c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10141c9747a4653aec1395c2bd6896c9b87cb5447837James Dong chunkIt->mSamples.clear(); 10151c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info->mChunks.erase(chunkIt); 10161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 10171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10181c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::writeChunks() { 10191c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("writeChunks"); 10201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong size_t outstandingChunks = 0; 10211c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mChunkInfos.empty()) { 10221c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<ChunkInfo>::iterator it = mChunkInfos.begin(); 10231c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!it->mChunks.empty()) { 10241c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(OK, writeOneChunk()); 10251c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ++outstandingChunks; 10261c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10271c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it->mTrack = NULL; 10281c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.erase(it); 10291c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10301c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.clear(); 10311c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGD("%d chunks are written in the last batch", outstandingChunks); 10321c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 10331c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10341c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::writeOneChunk() { 10351c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("writeOneChunk"); 10361c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10371c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Find the smallest timestamp, and write that chunk out 10381c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // XXX: What if some track is just too slow? 10391c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL; 10401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Track *track = NULL; 10411c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 10421c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 10431c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!it->mChunks.empty()) { 10441c9747a4653aec1395c2bd6896c9b87cb5447837James Dong List<Chunk>::iterator chunkIt = it->mChunks.begin(); 10451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (chunkIt->mTimeStampUs < minTimestampUs) { 10461c9747a4653aec1395c2bd6896c9b87cb5447837James Dong minTimestampUs = chunkIt->mTimeStampUs; 10471c9747a4653aec1395c2bd6896c9b87cb5447837James Dong track = it->mTrack; 10481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10491c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10501c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10511c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10521c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (track == NULL) { 10531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("Nothing to be written after all"); 10541c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 10551c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10561c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10571c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsFirstChunk) { 10581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = false; 10591c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10601c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); 10611c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mChunkInfos.end(); ++it) { 10621c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (it->mTrack == track) { 10631c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writeFirstChunk(&(*it)); 10641c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10651c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10661c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 10671c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 10681c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10691c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::threadFunc() { 10701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("threadFunc"); 10711c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10721c9747a4653aec1395c2bd6896c9b87cb5447837James Dong while (!mDone) { 10731c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 10741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 10751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkReadyCondition.wait(mLock); 10761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong CHECK_EQ(writeOneChunk(), OK); 10771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10781c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10791c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10801c9747a4653aec1395c2bd6896c9b87cb5447837James Dong { 10811c9747a4653aec1395c2bd6896c9b87cb5447837James Dong // Write ALL samples 10821c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Mutex::Autolock autolock(mLock); 10831c9747a4653aec1395c2bd6896c9b87cb5447837James Dong writeChunks(); 10841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10851c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 10861c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10871c9747a4653aec1395c2bd6896c9b87cb5447837James Dongstatus_t MPEG4Writer::startWriterThread() { 10881c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("startWriterThread"); 10891c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 10901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mDone = false; 10911c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsFirstChunk = true; 1092e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mDriftTimeUs = 0; 10931c9747a4653aec1395c2bd6896c9b87cb5447837James Dong for (List<Track *>::iterator it = mTracks.begin(); 10941c9747a4653aec1395c2bd6896c9b87cb5447837James Dong it != mTracks.end(); ++it) { 10951c9747a4653aec1395c2bd6896c9b87cb5447837James Dong ChunkInfo info; 10961c9747a4653aec1395c2bd6896c9b87cb5447837James Dong info.mTrack = *it; 10971c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mChunkInfos.push_back(info); 10981c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } 10991c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11001c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_t attr; 11011c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_init(&attr); 11021c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 11031c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_create(&mThread, &attr, ThreadWrapper, this); 11041c9747a4653aec1395c2bd6896c9b87cb5447837James Dong pthread_attr_destroy(&attr); 11051c9747a4653aec1395c2bd6896c9b87cb5447837James Dong return OK; 11061c9747a4653aec1395c2bd6896c9b87cb5447837James Dong} 11071c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 11081f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 110993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t MPEG4Writer::Track::start(MetaData *params) { 1110a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (!mDone && mPaused) { 1111a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = false; 1112a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = true; 1113a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1114a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 111525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 111693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t startTimeUs; 111719c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) { 111819c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber startTimeUs = 0; 111919c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber } 112019c9a1e2bb6ead5e1e895aea8be573fe0f8cc7bbAndreas Huber 1121e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mIsRealTimeRecording = true; 1122e259531ce59ab1f31de5a23124b22536f6a5a767James Dong { 1123e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int32_t isNotRealTime; 1124e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) { 1125e259531ce59ab1f31de5a23124b22536f6a5a767James Dong mIsRealTimeRecording = (isNotRealTime == 0); 1126e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1127e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1128e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 112993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong initTrackingProgressStatus(params); 113093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1131f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong sp<MetaData> meta = new MetaData; 1132f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong meta->setInt64(kKeyTime, startTimeUs); 1133f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong status_t err = mSource->start(meta.get()); 113425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber if (err != OK) { 113525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mDone = mReachedEOS = true; 113625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return err; 113725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 113820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 113920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_t attr; 114020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_init(&attr); 114120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 114220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = false; 1144c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = 0; 114525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = false; 1146956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mEstimatedTrackSizeBytes = 0; 11471f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStcoTableEntries = 0; 11481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStssTableEntries = 0; 11491f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumStscTableEntries = 0; 11501f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mNumSttsTableEntries = 0; 11511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes = 0; 115220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber pthread_create(&mThread, &attr, ThreadWrapper, this); 115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_attr_destroy(&attr); 115525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 115625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return OK; 115720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 115820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115937187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::pause() { 1160a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mPaused = true; 116137187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 1162a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1163a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 116437187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::stop() { 116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mDone) { 116637187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDone = true; 117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dummy; 117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber pthread_join(mThread, &dummy); 117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = (status_t) dummy; 117537187916a486504acaf83bea30147eb5fbf46ae5James Dong 117637187916a486504acaf83bea30147eb5fbf46ae5James Dong { 117737187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t status = mSource->stop(); 117837187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == OK && status != OK && status != ERROR_END_OF_STREAM) { 117937187916a486504acaf83bea30147eb5fbf46ae5James Dong err = status; 118037187916a486504acaf83bea30147eb5fbf46ae5James Dong } 118137187916a486504acaf83bea30147eb5fbf46ae5James Dong } 118237187916a486504acaf83bea30147eb5fbf46ae5James Dong 118337187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huberbool MPEG4Writer::Track::reachedEOS() { 118725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber return mReachedEOS; 118825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber} 118925b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid *MPEG4Writer::Track::ThreadWrapper(void *me) { 119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = static_cast<Track *>(me); 119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = track->threadEntry(); 119537187916a486504acaf83bea30147eb5fbf46ae5James Dong return (void *) err; 119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic void getNalUnitType(uint8_t byte, uint8_t* type) { 11993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("getNalUnitType: %d", byte); 12003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // nal_unit_type: 5-bit unsigned integer 12023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *type = (byte & 0x1F); 12033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 12043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatic const uint8_t *findNextStartCode( 12063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length) { 12073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("findNextStartCode: %p %d", data, length); 12093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = length; 12113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && 12123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { 12133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong --bytesLeft; 12143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (bytesLeft <= 4) { 12163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft = 0; // Last parameter set 12173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return &data[length - bytesLeft]; 12193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 12203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongconst uint8_t *MPEG4Writer::Track::parseParamSet( 12223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t length, int type, size_t *paramSetLen) { 12233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("parseParamSet"); 12253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong CHECK(type == kNalUnitTypeSeqParamSet || 12263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong type == kNalUnitTypePicParamSet); 12273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = findNextStartCode(data, length); 12293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong *paramSetLen = nextStartCode - data; 12303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen == 0) { 12313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Param set is malformed, since its length is 0"); 12323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 12333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong AVCParamSet paramSet(*paramSetLen, data); 12363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 12373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (*paramSetLen < 4) { 12383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Seq parameter set malformed"); 12393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 12403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mSeqParamSets.empty()) { 12423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc = data[1]; 12433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible = data[2]; 12443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc = data[3]; 12453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 12463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc != data[1] || 12473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileCompatible != data[2] || 12483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mLevelIdc != data[3]) { 12493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Inconsistent profile/level found in seq parameter sets"); 12503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return NULL; 12513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mSeqParamSets.push_back(paramSet); 12543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 12553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mPicParamSets.push_back(paramSet); 12563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return nextStartCode; 12583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 12593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::copyAVCCodecSpecificData( 12613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 12623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("copyAVCCodecSpecificData"); 12633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 2 bytes for each of the parameter set length field 12653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // plus the 7 bytes for the header 12663266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4 + 7) { 12673266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Codec specific data length too short: %d", size); 12683266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 12693266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12703266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12713266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = size; 12723266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificData = malloc(size); 12733266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(mCodecSpecificData, data, size); 12743266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 12753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 12763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12773266b2c04867f687e1e1b7b86088d6eb83077fd0James Dongstatus_t MPEG4Writer::Track::parseAVCCodecSpecificData( 12783266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *data, size_t size) { 12793266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 12803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGV("parseAVCCodecSpecificData"); 12813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data starts with a start code. 12823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS and PPS are separated with start codes. 12833266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Also, SPS must come before PPS 12843266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint8_t type = kNalUnitTypeSeqParamSet; 12853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotSps = false; 12863266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bool gotPps = false; 12873266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *tmp = data; 12883266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong const uint8_t *nextStartCode = data; 12893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t bytesLeft = size; 12903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t paramSetLen = 0; 12913266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize = 0; 12923266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { 12933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong getNalUnitType(*(tmp + 4), &type); 12943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (type == kNalUnitTypeSeqParamSet) { 12953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (gotPps) { 12963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("SPS must come before PPS"); 12973266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 12983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 12993266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 13003266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotSps = true; 13013266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13023266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 13033266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else if (type == kNalUnitTypePicParamSet) { 13043266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotSps) { 13053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("SPS must come before PPS"); 13063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (!gotPps) { 13093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong gotPps = true; 13103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, ¶mSetLen); 13123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } else { 13133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Only SPS and PPS Nal units are expected"); 13143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nextStartCode == NULL) { 13183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Move on to find the next parameter set 13223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong bytesLeft -= nextStartCode - tmp; 13233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong tmp = nextStartCode; 13243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += (2 + paramSetLen); 13253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 13283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of seq parameter sets 13293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nSeqParamSets = mSeqParamSets.size(); 13303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets == 0) { 13313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Cound not find sequence parameter set"); 13323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nSeqParamSets > 0x1F) { 13363266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Too many seq parameter sets (%d) found", nSeqParamSets); 13373266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13383266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13393266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13403266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13413266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 13423266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the number of pic parameter sets 13433266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong size_t nPicParamSets = mPicParamSets.size(); 13443266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets == 0) { 13453266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Cound not find picture parameter set"); 13463266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13473266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13483266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (nPicParamSets > 0xFF) { 13493266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Too many pic parameter sets (%d) found", nPicParamSets); 13503266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return ERROR_MALFORMED; 13513266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13523266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13533266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13543266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong { 13553266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Check on the profiles 13563266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // These profiles requires additional parameter set extensions 13573266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (mProfileIdc == 100 || mProfileIdc == 110 || 13583266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mProfileIdc == 122 || mProfileIdc == 144) { 13593266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Sorry, no support for profile_idc: %d!", mProfileIdc); 13603266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return BAD_VALUE; 13613266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13623266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 13633266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 13643266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return OK; 13653266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong} 1366548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 136703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huberstatus_t MPEG4Writer::Track::makeAVCCodecSpecificData( 136803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber const uint8_t *data, size_t size) { 1369548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 137003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (mCodecSpecificData != NULL) { 1371548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber LOGE("Already have codec specific data"); 137203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 137303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 137403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 13753266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (size < 4) { 13763266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong LOGE("Codec specific data length too short: %d", size); 137703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 137803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 137903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 13803266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // Data is in the form of AVCCodecSpecificData 13813266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (memcmp("\x00\x00\x00\x01", data, 4)) { 13823266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong return copyAVCCodecSpecificData(data, size); 138303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 138403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 13853266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong if (parseAVCCodecSpecificData(data, size) != OK) { 138603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return ERROR_MALFORMED; 138703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber } 138803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 13893266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // ISO 14496-15: AVC file format 13903266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong mCodecSpecificDataSize += 7; // 7 more bytes in the header 139103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 139203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber uint8_t *header = (uint8_t *)mCodecSpecificData; 13933266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = 1; // version 13943266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = mProfileIdc; // profile indication 13953266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[2] = mProfileCompatible; // profile compatibility 13963266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[3] = mLevelIdc; 139703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 13983266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne 1399b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 1400b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 3; // length size == 4 bytes 1401b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 1402b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong header[4] = 0xfc | 1; // length size == 2 bytes 1403b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 140403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 14053266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 3-bit '111' followed by 5-bit numSequenceParameterSets 14063266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nSequenceParamSets = mSeqParamSets.size(); 14073266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[5] = 0xe0 | nSequenceParamSets; 14083266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 6; 14093266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mSeqParamSets.begin(); 14103266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mSeqParamSets.end(); ++it) { 14113266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit sequence parameter set length 14123266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t seqParamSetLength = it->mLength; 14133266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = seqParamSetLength >> 8; 14143266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = seqParamSetLength & 0xff; 14153266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14163266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // SPS NAL unit (sequence parameter length bytes) 14173266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, seqParamSetLength); 14183266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + seqParamSetLength); 14193266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 14203266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14213266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 8-bit nPictureParameterSets 14223266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong int nPictureParamSets = mPicParamSets.size(); 14233266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = nPictureParamSets; 14243266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += 1; 14253266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong for (List<AVCParamSet>::iterator it = mPicParamSets.begin(); 14263266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong it != mPicParamSets.end(); ++it) { 14273266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // 16-bit picture parameter set length 14283266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong uint16_t picParamSetLength = it->mLength; 14293266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[0] = picParamSetLength >> 8; 14303266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header[1] = picParamSetLength & 0xff; 14313266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong 14323266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong // PPS Nal unit (picture parameter set length bytes) 14333266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong memcpy(&header[2], it->mData, picParamSetLength); 14343266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong header += (2 + picParamSetLength); 14353266b2c04867f687e1e1b7b86088d6eb83077fd0James Dong } 143603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 143703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber return OK; 143803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber} 143903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber 144037187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t MPEG4Writer::Track::threadEntry() { 144130ab66297501757d745b9ae10da61adcd891f497Andreas Huber int32_t count = 0; 144213aec890216948b0c364f8f92792129d0335f506James Dong const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 144313aec890216948b0c364f8f92792129d0335f506James Dong int64_t chunkTimestampUs = 0; 144413aec890216948b0c364f8f92792129d0335f506James Dong int32_t nChunks = 0; 144513aec890216948b0c364f8f92792129d0335f506James Dong int32_t nZeroLengthFrames = 0; 14468f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t lastTimestampUs = 0; // Previous sample time stamp in ms 14478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t lastDurationUs = 0; // Between the previous two samples in ms 1448c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t currDurationTicks = 0; // Timescale based ticks 1449c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t lastDurationTicks = 0; // Timescale based ticks 14508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t sampleCount = 1; // Sample count in the current stts table entry 1451be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong uint32_t previousSampleSize = 0; // Size of the previous sample 1452a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong int64_t previousPausedDurationUs = 0; 14531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong int64_t timestampUs; 1454e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1455d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong sp<MetaData> meta_data; 145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1457ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mNumSamples = 0; 145893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong status_t err = OK; 145920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 146093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong while (!mDone && (err = mSource->read(&buffer)) == OK) { 146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (buffer->range_length() == 0) { 146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 146320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 146413aec890216948b0c364f8f92792129d0335f506James Dong ++nZeroLengthFrames; 146520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 146620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 146720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1468a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // If the codec specific data has not been received yet, delay pause. 1469a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // After the codec specific data is received, discard what we received 1470a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong // when the track is to be paused. 1471a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mPaused && !mResumed) { 1472a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer->release(); 1473a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong buffer = NULL; 1474a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong continue; 1475a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1476a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 147730ab66297501757d745b9ae10da61adcd891f497Andreas Huber ++count; 147830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 147903b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber int32_t isCodecConfig; 148003b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 148103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber && isCodecConfig) { 1482548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber CHECK(!mGotAllCodecSpecificData); 1483548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber 14841c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) { 148503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber status_t err = makeAVCCodecSpecificData( 148603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 148703b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 148803b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 1489be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong CHECK_EQ(OK, err); 14901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong } else if (mIsMPEG4) { 149103b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificDataSize = buffer->range_length(); 149203b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber mCodecSpecificData = malloc(mCodecSpecificDataSize); 149303b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber memcpy(mCodecSpecificData, 149403b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber (const uint8_t *)buffer->data() 149503b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber + buffer->range_offset(), 149603b268eac37ca2589bfff0bf58daf79d29cc14f4Andreas Huber buffer->range_length()); 149730ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 149830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 149930ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer->release(); 150030ab66297501757d745b9ae10da61adcd891f497Andreas Huber buffer = NULL; 150130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1502548e31844937b37518fbb62ff69e9ff1f794183bAndreas Huber mGotAllCodecSpecificData = true; 150330ab66297501757d745b9ae10da61adcd891f497Andreas Huber continue; 1504a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1505a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1506d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // Make a deep copy of the MediaBuffer and Metadata and release 1507d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong // the original as soon as we can 1508d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 1509d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 1510d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->range_length()); 1511d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong copy->set_range(0, buffer->range_length()); 1512d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data = new MetaData(*buffer->meta_data().get()); 1513d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer->release(); 1514d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong buffer = NULL; 1515d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 15161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAvc) StripStartcode(copy); 1517e136c3bb38e88315bf8797a464ebf2c788296b22James Dong 1518b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong size_t sampleSize = copy->range_length(); 1519b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mIsAvc) { 1520b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong if (mOwner->useNalLengthFour()) { 1521b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 4; 1522b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } else { 1523b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong sampleSize += 2; 1524b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 1525b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong } 1526050b28a593350047845a45a14cc5026221ac1620James Dong 1527d599cd4573b5a2d5914c5040e0565ef866749b77James Dong // Max file size or duration handling 15281f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mMdatSizeBytes += sampleSize; 15291f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong updateTrackSizeEstimate(); 15301f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong 1531d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileSizeLimit()) { 1532d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); 1533d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1534d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1535d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mOwner->exceedsFileDurationLimit()) { 1536d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); 1537d599cd4573b5a2d5914c5040e0565ef866749b77James Dong break; 1538d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1539d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1540050b28a593350047845a45a14cc5026221ac1620James Dong 1541d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong int32_t isSync = false; 1542d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong meta_data->findInt32(kKeyIsSyncFrame, &isSync); 1543d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1544d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); 1545d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 1546d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong//////////////////////////////////////////////////////////////////////////////// 15478644c14618d30d9e57a69df40ed939986ebf02c4James Dong if (mSampleSizes.empty()) { 1548f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimestampUs = timestampUs; 1549f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mOwner->setStartTimestampUs(mStartTimestampUs); 15503c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 155148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber 1552a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mResumed) { 1553c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong previousPausedDurationUs += (timestampUs - mTrackDurationUs - lastDurationUs); 1554a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mResumed = false; 1555a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1556a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 1557a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs -= previousPausedDurationUs; 1558e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (mIsRealTimeRecording && !mIsAudio) { 1559e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // The minor adjustment on the timestamp is heuristic/experimental 1560e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // We are adjusting the timestamp to reduce the fluctuation of the duration 1561e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // of neighboring samples. This in turn helps reduce the track header size, 1562e259531ce59ab1f31de5a23124b22536f6a5a767James Dong // especially, the number of entries in the "stts" box. 1563e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (mNumSamples > 1) { 1564d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong int64_t currDriftTimeUs = mOwner->getDriftTimeUs(); 1565d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong int64_t durationUs = timestampUs + currDriftTimeUs - lastTimestampUs; 1566e259531ce59ab1f31de5a23124b22536f6a5a767James Dong int64_t diffUs = (durationUs > lastDurationUs) 1567e259531ce59ab1f31de5a23124b22536f6a5a767James Dong ? durationUs - lastDurationUs 1568e259531ce59ab1f31de5a23124b22536f6a5a767James Dong : lastDurationUs - durationUs; 1569e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (diffUs <= 5000) { // XXX: Magic number 5ms 1570e259531ce59ab1f31de5a23124b22536f6a5a767James Dong timestampUs = lastTimestampUs + lastDurationUs; 1571e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } else { 1572d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong timestampUs += currDriftTimeUs; 1573e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1574e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1575e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1576e259531ce59ab1f31de5a23124b22536f6a5a767James Dong CHECK(timestampUs >= 0); 1577e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (mNumSamples > 1) { 1578e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (timestampUs <= lastTimestampUs) { 15794f86a980fee1880dca61b828599fa6d76755a485James Dong LOGW("Frame arrives too late!"); 15804f86a980fee1880dca61b828599fa6d76755a485James Dong // Don't drop the late frame, since dropping a frame may cause 15814f86a980fee1880dca61b828599fa6d76755a485James Dong // problems later during playback 15824f86a980fee1880dca61b828599fa6d76755a485James Dong 15834f86a980fee1880dca61b828599fa6d76755a485James Dong // The idea here is to avoid having two or more samples with the 15844f86a980fee1880dca61b828599fa6d76755a485James Dong // same timestamp in the output file. 15854f86a980fee1880dca61b828599fa6d76755a485James Dong if (mTimeScale >= 1000000LL) { 158640e9940fadf22daa64c1e766fa8a855c7b149c17James Dong timestampUs = lastTimestampUs + 1; 15874f86a980fee1880dca61b828599fa6d76755a485James Dong } else { 158840e9940fadf22daa64c1e766fa8a855c7b149c17James Dong timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale; 15894f86a980fee1880dca61b828599fa6d76755a485James Dong } 1590e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1591e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1592e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1593a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong LOGV("time stamp: %lld and previous paused duration %lld", 1594a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong timestampUs, previousPausedDurationUs); 1595c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong if (timestampUs > mTrackDurationUs) { 1596c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs = timestampUs; 15973b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber } 15983b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huber 15998644c14618d30d9e57a69df40ed939986ebf02c4James Dong mSampleSizes.push_back(sampleSize); 1600ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong ++mNumSamples; 1601ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples > 2) { 1602c059860c73678a202bfa33062723e8f82fb779d9James Dong // We need to use the time scale based ticks, rather than the 1603c059860c73678a202bfa33062723e8f82fb779d9James Dong // timestamp itself to determine whether we have to use a new 1604c059860c73678a202bfa33062723e8f82fb779d9James Dong // stts entry, since we may have rounding errors. 1605c059860c73678a202bfa33062723e8f82fb779d9James Dong // The calculation is intended to reduce the accumulated 1606c059860c73678a202bfa33062723e8f82fb779d9James Dong // rounding errors. 1607c059860c73678a202bfa33062723e8f82fb779d9James Dong currDurationTicks = 1608c059860c73678a202bfa33062723e8f82fb779d9James Dong ((timestampUs * mTimeScale + 500000LL) / 1000000LL - 1609c059860c73678a202bfa33062723e8f82fb779d9James Dong (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL); 1610c059860c73678a202bfa33062723e8f82fb779d9James Dong 1611c059860c73678a202bfa33062723e8f82fb779d9James Dong if (currDurationTicks != lastDurationTicks) { 16121f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneSttsTableEntry(sampleCount, lastDurationUs); 1613be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong sampleCount = 1; 1614be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1615be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; 1616be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1617be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 1618be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 1619ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples >= 2 && previousSampleSize != sampleSize) { 1620be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mSamplesHaveSameSize = false; 1621be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 16228644c14618d30d9e57a69df40ed939986ebf02c4James Dong previousSampleSize = sampleSize; 1623be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 16248644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastDurationUs = timestampUs - lastTimestampUs; 1625c059860c73678a202bfa33062723e8f82fb779d9James Dong lastDurationTicks = currDurationTicks; 16268644c14618d30d9e57a69df40ed939986ebf02c4James Dong lastTimestampUs = timestampUs; 1627e259531ce59ab1f31de5a23124b22536f6a5a767James Dong if (mIsRealTimeRecording && mIsAudio) { 1628d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong int64_t driftTimeUs = 0; 1629d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong if (meta_data->findInt64(kKeyDriftTime, &driftTimeUs)) { 1630d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mOwner->setDriftTimeUs(driftTimeUs); 1631e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 1632e259531ce59ab1f31de5a23124b22536f6a5a767James Dong } 163320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1634d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong if (isSync != 0) { 16351f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStssTableEntry(mNumSamples); 1636d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong } 1637d07139e2e817a9b3ae9c87ba4e1e8d65d3e549daJames Dong 163893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackingProgressStatus) { 163993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mPreviousTrackTimeUs <= 0) { 164093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = mStartTimestampUs; 164193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 1642faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackProgressStatus(timestampUs); 164393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 164458ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mOwner->numTracks() == 1) { 16451c9747a4653aec1395c2bd6896c9b87cb5447837James Dong off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy) 164658ae9c530247668f8af36e30d228c716c226b3d4James Dong : mOwner->addSample_l(copy); 164758ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mChunkOffsets.empty()) { 16481f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addChunkOffset(offset); 164958ae9c530247668f8af36e30d228c716c226b3d4James Dong } 165058ae9c530247668f8af36e30d228c716c226b3d4James Dong copy->release(); 165158ae9c530247668f8af36e30d228c716c226b3d4James Dong copy = NULL; 165258ae9c530247668f8af36e30d228c716c226b3d4James Dong continue; 165358ae9c530247668f8af36e30d228c716c226b3d4James Dong } 165413aec890216948b0c364f8f92792129d0335f506James Dong 165513aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.push_back(copy); 165613aec890216948b0c364f8f92792129d0335f506James Dong if (interleaveDurationUs == 0) { 16571f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, 1); 16581c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 165913aec890216948b0c364f8f92792129d0335f506James Dong } else { 166013aec890216948b0c364f8f92792129d0335f506James Dong if (chunkTimestampUs == 0) { 166113aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 166213aec890216948b0c364f8f92792129d0335f506James Dong } else { 166313aec890216948b0c364f8f92792129d0335f506James Dong if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 166413aec890216948b0c364f8f92792129d0335f506James Dong ++nChunks; 166513aec890216948b0c364f8f92792129d0335f506James Dong if (nChunks == 1 || // First chunk 166613aec890216948b0c364f8f92792129d0335f506James Dong (--(mStscTableEntries.end()))->samplesPerChunk != 166713aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.size()) { 16681f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(nChunks, mChunkSamples.size()); 166913aec890216948b0c364f8f92792129d0335f506James Dong } 16701c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 167113aec890216948b0c364f8f92792129d0335f506James Dong chunkTimestampUs = timestampUs; 167213aec890216948b0c364f8f92792129d0335f506James Dong } 167313aec890216948b0c364f8f92792129d0335f506James Dong } 167413aec890216948b0c364f8f92792129d0335f506James Dong } 167513aec890216948b0c364f8f92792129d0335f506James Dong 167620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 167725b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 16788644c14618d30d9e57a69df40ed939986ebf02c4James Dong if (mSampleSizes.empty()) { 167937187916a486504acaf83bea30147eb5fbf46ae5James Dong err = ERROR_MALFORMED; 1680690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else if (OK != checkCodecSpecificData()) { 1681690f546b0ee548dbfe997df36418e5302ec2d786James Dong err = ERROR_MALFORMED; 1682f0ce2fb0c7bf3a414279e5aba61105f3d9025c0eJames Dong } 1683faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong mOwner->trackProgressStatus(this, -1, err); 1684be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong 168513aec890216948b0c364f8f92792129d0335f506James Dong // Last chunk 168658ae9c530247668f8af36e30d228c716c226b3d4James Dong if (mOwner->numTracks() == 1) { 16871f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(1, mNumSamples); 168858ae9c530247668f8af36e30d228c716c226b3d4James Dong } else if (!mChunkSamples.empty()) { 16891f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneStscTableEntry(++nChunks, mChunkSamples.size()); 16901c9747a4653aec1395c2bd6896c9b87cb5447837James Dong bufferChunk(timestampUs); 169113aec890216948b0c364f8f92792129d0335f506James Dong } 169213aec890216948b0c364f8f92792129d0335f506James Dong 1693be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // We don't really know how long the last frame lasts, since 1694be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // there is no frame time after it, just repeat the previous 1695be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong // frame's duration. 1696ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong if (mNumSamples == 1) { 16978f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong lastDurationUs = 0; // A single sample's duration 1698be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 1699be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong ++sampleCount; // Count for the last sample 1700be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 17011f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong addOneSttsTableEntry(sampleCount, lastDurationUs); 1702c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong mTrackDurationUs += lastDurationUs; 170325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mReachedEOS = true; 17041f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s", 17051f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video"); 1706365a963142093a1cd8efdcea76b5f65096a5b115James Dong 170737187916a486504acaf83bea30147eb5fbf46ae5James Dong if (err == ERROR_END_OF_STREAM) { 170837187916a486504acaf83bea30147eb5fbf46ae5James Dong return OK; 170937187916a486504acaf83bea30147eb5fbf46ae5James Dong } 171037187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 1711365a963142093a1cd8efdcea76b5f65096a5b115James Dong} 1712365a963142093a1cd8efdcea76b5f65096a5b115James Dong 1713faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { 1714faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong LOGV("trackProgressStatus: %lld us", timeUs); 1715215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong if (mTrackEveryTimeDurationUs > 0 && 1716215381ea729086b8359b7f59bdc2bd7cf55a0c45James Dong timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) { 171793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("Fire time tracking progress status at %lld us", timeUs); 1718faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err); 171993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mPreviousTrackTimeUs = timeUs; 172093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 172193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 172293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 1723faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dongvoid MPEG4Writer::trackProgressStatus( 1724faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong const MPEG4Writer::Track* track, int64_t timeUs, status_t err) { 1725faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong Mutex::Autolock lock(mLock); 1726faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong int32_t nTracks = mTracks.size(); 1727faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong CHECK(nTracks >= 1); 1728faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong CHECK(nTracks < 64); // Arbitrary number 1729faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1730faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong int32_t trackNum = 0; 1731faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong CHECK(trackNum < nTracks); 1732faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum <<= 16; 1733faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1734faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Error notification 1735faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Do not consider ERROR_END_OF_STREAM an error 1736faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (err != OK && err != ERROR_END_OF_STREAM) { 1737faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong notify(MEDIA_RECORDER_EVENT_ERROR, 1738faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum | MEDIA_RECORDER_ERROR_UNKNOWN, 1739faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 1740faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 1741faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 1742faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1743faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong if (timeUs == -1) { 1744faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send completion notification 1745faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong notify(MEDIA_RECORDER_EVENT_INFO, 1746faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS, 1747faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong err); 1748faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong return; 1749faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } else { 1750faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong // Send progress status 1751faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong notify(MEDIA_RECORDER_EVENT_INFO, 1752faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS, 1753faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong timeUs / 1000); 1754faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong } 1755faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong} 1756faed5cd124a54b8db3429f4c26b3220bbec4c8bbJames Dong 1757d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dongvoid MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) { 1758d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong LOGV("setDriftTimeUs: %lld us", driftTimeUs); 1759e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 1760d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mDriftTimeUs = driftTimeUs; 1761e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 1762e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1763e259531ce59ab1f31de5a23124b22536f6a5a767James Dongint64_t MPEG4Writer::getDriftTimeUs() { 1764e259531ce59ab1f31de5a23124b22536f6a5a767James Dong LOGV("getDriftTimeUs: %lld us", mDriftTimeUs); 1765e259531ce59ab1f31de5a23124b22536f6a5a767James Dong Mutex::Autolock autolock(mLock); 1766e259531ce59ab1f31de5a23124b22536f6a5a767James Dong return mDriftTimeUs; 1767e259531ce59ab1f31de5a23124b22536f6a5a767James Dong} 1768e259531ce59ab1f31de5a23124b22536f6a5a767James Dong 1769b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dongbool MPEG4Writer::useNalLengthFour() { 1770b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong return mUse4ByteNalLength; 1771b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong} 1772b4d5320bda29cd9694461c9b61d0211f801ff0afJames Dong 17731c9747a4653aec1395c2bd6896c9b87cb5447837James Dongvoid MPEG4Writer::Track::bufferChunk(int64_t timestampUs) { 17741c9747a4653aec1395c2bd6896c9b87cb5447837James Dong LOGV("bufferChunk"); 17751c9747a4653aec1395c2bd6896c9b87cb5447837James Dong 17761c9747a4653aec1395c2bd6896c9b87cb5447837James Dong Chunk chunk(this, timestampUs, mChunkSamples); 17771c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->bufferChunk(chunk); 177813aec890216948b0c364f8f92792129d0335f506James Dong mChunkSamples.clear(); 177920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 178020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17813b240d6bf235f6f6b40ee4c37a2862de286ca1e4Andreas Huberint64_t MPEG4Writer::Track::getDurationUs() const { 1782c5f0c714dc4225cd2ec305d5ddd297964a3dd3dcJames Dong return mTrackDurationUs; 178320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 178420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1785d599cd4573b5a2d5914c5040e0565ef866749b77James Dongint64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 1786d599cd4573b5a2d5914c5040e0565ef866749b77James Dong return mEstimatedTrackSizeBytes; 1787d599cd4573b5a2d5914c5040e0565ef866749b77James Dong} 1788d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 1789690f546b0ee548dbfe997df36418e5302ec2d786James Dongstatus_t MPEG4Writer::Track::checkCodecSpecificData() const { 1790690f546b0ee548dbfe997df36418e5302ec2d786James Dong const char *mime; 1791690f546b0ee548dbfe997df36418e5302ec2d786James Dong CHECK(mMeta->findCString(kKeyMIMEType, &mime)); 1792690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) || 1793690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) || 1794690f546b0ee548dbfe997df36418e5302ec2d786James Dong !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 1795690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (!mCodecSpecificData || 1796690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize <= 0) { 1797690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Missing codec specific data 1798690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 1799690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 1800690f546b0ee548dbfe997df36418e5302ec2d786James Dong } else { 1801690f546b0ee548dbfe997df36418e5302ec2d786James Dong if (mCodecSpecificData || 1802690f546b0ee548dbfe997df36418e5302ec2d786James Dong mCodecSpecificDataSize > 0) { 1803690f546b0ee548dbfe997df36418e5302ec2d786James Dong // Unexepected codec specific data found 1804690f546b0ee548dbfe997df36418e5302ec2d786James Dong return ERROR_MALFORMED; 1805690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 1806690f546b0ee548dbfe997df36418e5302ec2d786James Dong } 1807690f546b0ee548dbfe997df36418e5302ec2d786James Dong return OK; 1808690f546b0ee548dbfe997df36418e5302ec2d786James Dong} 1809690f546b0ee548dbfe997df36418e5302ec2d786James Dong 18101acfe8649f8169caf2ff098c2dc2de880d9a3760James Dongvoid MPEG4Writer::Track::writeTrackHeader( 18111acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong int32_t trackID, bool use32BitOffset) { 181220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 181320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findCString(kKeyMIMEType, &mime); 18140c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 181520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18168f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("%s track time scale: %d", 18171c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mIsAudio? "Audio": "Video", mTimeScale); 18188f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 181920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber time_t now = time(NULL); 18208f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mvhdTimeScale = mOwner->getTimeScale(); 18218f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t trakDurationUs = getDurationUs(); 182220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 182320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("trak"); 182420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 182520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("tkhd"); 18261acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Flags = 7 to indicate that the track is enabled, and 18271acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // part of the presentation 18281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0x07); // version=0, flags=7 182920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 183020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 183120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(trackID); 183220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 18338f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t tkhdDuration = 18348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 18358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(tkhdDuration); // in mvhd timescale 183620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 183720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 183820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // layer 183920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // alternate group 18401c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume 184120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 184220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 184320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); // matrix 184420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 184520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 184620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 184720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x10000); 184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 184920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 185120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x40000000); 185220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAudio) { 185420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 185520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); 185620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 185720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 185820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 185920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 18600c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 186120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1862050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(width << 16); // 32-bit fixed-point value 1863050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(height << 16); // 32-bit fixed-point value 186420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 186520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // tkhd 186620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1867f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t moovStartTimeUs = mOwner->getStartTimestampUs(); 1868f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (mStartTimestampUs != moovStartTimeUs) { 18693c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("edts"); 18703c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->beginBox("elst"); 18711acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0); // version=0, flags=0: 32-bit time 18721acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(2); // never ends with an empty list 18738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 18748f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // First elst entry: specify the starting time offset 18758f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int64_t offsetUs = mStartTimestampUs - moovStartTimeUs; 18768f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6; 18778f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(seg); // in mvhd timecale 18788f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(-1); // starting time offset 18798f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(1 << 16); // rate = 1.0 18808f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 18818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // Second elst entry: specify the track duration 18828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6; 18838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(seg); // in mvhd timescale 18841acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0); 18851acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); 18863c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 18873c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong mOwner->endBox(); 18883c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong } 18893c0131f02b6f008321608044c53bccce2ac5f6ddJames Dong 189020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdia"); 189120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 189220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mdhd"); 189320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 189420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // creation time 189520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(now); // modification time 18968f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(mTimeScale); // media timescale 18978f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6; 18988f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(mdhdDuration); // use media timescale 18991acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Language follows the three letter standard ISO-639-2/T 19001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // 'e', 'n', 'g' for "English", for instance. 19011acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Each character is packed as the difference between its ASCII value and 0x60. 19021acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // For "English", these are 00101, 01110, 00111. 19031acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // XXX: Where is the padding bit located: 0x15C7? 19041acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt16(0); // language code 190520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 190620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 190720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 190820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("hdlr"); 190920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 1910050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // component type: should be mhlr 19111c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype 191220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 191320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 191420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 19151acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // Removing "r" for the name string just makes the string 4 byte aligned 19161c9747a4653aec1395c2bd6896c9b87cb5447837James Dong mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name 191720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 191820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 191920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("minf"); 19201c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAudio) { 192120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("smhd"); 192220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 192320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // balance 192420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 192520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 192620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 192720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("vmhd"); 19281acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(0x01); // version=0, flags=1 192920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // graphics mode 193020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // opcolor 193120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 193220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); 193320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 193420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1935050b28a593350047845a45a14cc5026221ac1620James Dong 1936050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dinf"); 1937050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("dref"); 1938050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 19391acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1); // entry count (either url or urn) 19401acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // The table index here refers to the sample description index 19411acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // in the sample table entries. 1942050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("url "); 19431acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1); // version=0, flags=1 (self-contained) 1944050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // url 1945050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dref 1946050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // dinf 1947050b28a593350047845a45a14cc5026221ac1620James Dong 194820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stbl"); 194920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 195020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsd"); 195120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 195220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(1); // entry count 19531c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (mIsAudio) { 195425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber const char *fourcc = NULL; 195518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 195625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "samr"; 195718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 195825b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber fourcc = "sawb"; 1959050b28a593350047845a45a14cc5026221ac1620James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1960050b28a593350047845a45a14cc5026221ac1620James Dong fourcc = "mp4a"; 196125b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } else { 196225b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 196325b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber CHECK(!"should not be here, unknown mime type."); 196425b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber } 196525b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber 196625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber mOwner->beginBox(fourcc); // audio format 196720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 196820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 1969050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x1); // data ref index 197020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 197120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 1972050b28a593350047845a45a14cc5026221ac1620James Dong int32_t nChannels; 1973050b28a593350047845a45a14cc5026221ac1620James Dong CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 1974050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(nChannels); // channel count 197520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(16); // sample size 197620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 197720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 197820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 197920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t samplerate; 198020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 19810c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 198220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(samplerate << 16); 1983050b28a593350047845a45a14cc5026221ac1620James Dong if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1984050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("esds"); 198551dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong CHECK(mCodecSpecificData); 198651dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong CHECK(mCodecSpecificDataSize > 0); 1987050b28a593350047845a45a14cc5026221ac1620James Dong 1988050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 1989050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x03); // ES_DescrTag 1990050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(23 + mCodecSpecificDataSize); 1991050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x0000);// ES_ID 1992050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); 1993050b28a593350047845a45a14cc5026221ac1620James Dong 1994050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x04); // DecoderConfigDescrTag 1995050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(15 + mCodecSpecificDataSize); 1996050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 1997050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x15); // streamType AudioStream 1998050b28a593350047845a45a14cc5026221ac1620James Dong 1999050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt16(0x03); // XXX 2000050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x00); // buffer size 24-bit 2001050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // max bit rate 2002050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(96000); // avg bit rate 2003050b28a593350047845a45a14cc5026221ac1620James Dong 2004050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 2005050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt8(mCodecSpecificDataSize); 2006050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 2007050b28a593350047845a45a14cc5026221ac1620James Dong 2008050b28a593350047845a45a14cc5026221ac1620James Dong static const uint8_t kData2[] = { 2009050b28a593350047845a45a14cc5026221ac1620James Dong 0x06, // SLConfigDescriptorTag 2010050b28a593350047845a45a14cc5026221ac1620James Dong 0x01, 2011050b28a593350047845a45a14cc5026221ac1620James Dong 0x02 2012050b28a593350047845a45a14cc5026221ac1620James Dong }; 2013050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->write(kData2, sizeof(kData2)); 2014050b28a593350047845a45a14cc5026221ac1620James Dong 2015050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // esds 20165aff464f67322cd13dc8ed165806971cfff2e4d5James Dong } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) || 20175aff464f67322cd13dc8ed165806971cfff2e4d5James Dong !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 20185aff464f67322cd13dc8ed165806971cfff2e4d5James Dong // 3gpp2 Spec AMRSampleEntry fields 20195aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->beginBox("damr"); 20205aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeCString(" "); // vendor: 4 bytes 20215aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt8(0); // decoder version 20225aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt16(0x83FF); // mode set: all enabled 20235aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt8(0); // mode change period 20245aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->writeInt8(1); // frames per sample 20255aff464f67322cd13dc8ed165806971cfff2e4d5James Dong mOwner->endBox(); 2026050b28a593350047845a45a14cc5026221ac1620James Dong } 202720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); 202820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 202918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 203020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("mp4v"); 203118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 203220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("s263"); 203330ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 203430ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avc1"); 203520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 203625b130939339d57789a86fac837a2a8cedbcb7d8Andreas Huber LOGE("Unknown mime type '%s'.", mime); 20370c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!"should not be here, unknown mime type."); 203820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 203920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 204020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 204120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 20421acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt16(1); // data ref index 204320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // predefined 204420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0); // reserved 204520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 204620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 204720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // predefined 204820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 204920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t width, height; 205020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mMeta->findInt32(kKeyWidth, &width); 205120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && mMeta->findInt32(kKeyHeight, &height); 20520c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(success); 205320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 205420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(width); 205520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(height); 205620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // horiz resolution 205720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0x480000); // vert resolution 205820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // reserved 205920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(1); // frame count 206020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(" ", 32); 206120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x18); // depth 206220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(-1); // predefined 206320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20640c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(23 + mCodecSpecificDataSize < 128); 206520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 206618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 2067a37923e9a57d489e7bed2129369219039fa5f12cJames Dong CHECK(mCodecSpecificData); 2068a37923e9a57d489e7bed2129369219039fa5f12cJames Dong CHECK(mCodecSpecificDataSize > 0); 206920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("esds"); 207020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 207120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 207220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 207320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x03); // ES_DescrTag 207420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(23 + mCodecSpecificDataSize); 207520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt16(0x0000); // ES_ID 207620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x1f); 207720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 207820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x04); // DecoderConfigDescrTag 207920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(15 + mCodecSpecificDataSize); 208020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 208120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x11); // streamType VisualStream 208220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 208320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData[] = { 208420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 0x77, 0x00, 208520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00, 208620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x00, 0x03, 0xe8, 0x00 208720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 208820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData, sizeof(kData)); 2089050b28a593350047845a45a14cc5026221ac1620James Dong 209020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 209120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 209220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(mCodecSpecificDataSize); 209320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 209420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 209520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const uint8_t kData2[] = { 209620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x06, // SLConfigDescriptorTag 209720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x01, 209820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 0x02 209920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber }; 210020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->write(kData2, sizeof(kData2)); 210120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 210220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // esds 210318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 210420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("d263"); 210520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 210620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // vendor 210720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // decoder version 210820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(10); // level: 10 210920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt8(0); // profile: 0 211020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 211120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // d263 211230ab66297501757d745b9ae10da61adcd891f497Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 211351dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong CHECK(mCodecSpecificData); 211451dfe6d646ddcc5fc252aa4c19c9936d32af8ad7James Dong CHECK(mCodecSpecificDataSize > 0); 211530ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->beginBox("avcC"); 211630ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 211730ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // avcC 211820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 211930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 21201acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->beginBox("pasp"); 21211acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong // This is useful if the pixel is not square 21221acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // hspacing 21231acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(1 << 16); // vspacing 21241acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->endBox(); // pasp 212530ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOwner->endBox(); // mp4v, s263 or avc1 212620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 212720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsd 212820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 212920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stts"); 213020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 21311f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mOwner->writeInt32(mNumSttsTableEntries); 2132c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t prevTimestampUs = 0; 2133be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 2134be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong it != mSttsTableEntries.end(); ++it) { 2135be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(it->sampleCount); 2136c059860c73678a202bfa33062723e8f82fb779d9James Dong 2137c059860c73678a202bfa33062723e8f82fb779d9James Dong // Make sure that we are calculating the sample duration the exactly 2138c059860c73678a202bfa33062723e8f82fb779d9James Dong // same way as we made decision on how to create stts entries. 2139c059860c73678a202bfa33062723e8f82fb779d9James Dong int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs; 2140c059860c73678a202bfa33062723e8f82fb779d9James Dong int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL - 2141c059860c73678a202bfa33062723e8f82fb779d9James Dong (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL); 2142c059860c73678a202bfa33062723e8f82fb779d9James Dong prevTimestampUs += (it->sampleCount * it->sampleDurationUs); 2143c059860c73678a202bfa33062723e8f82fb779d9James Dong 21448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->writeInt32(dur); 214520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 214620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stts 214720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21481c9747a4653aec1395c2bd6896c9b87cb5447837James Dong if (!mIsAudio) { 2149050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->beginBox("stss"); 2150050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(0); // version=0, flags=0 21511f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mOwner->writeInt32(mNumStssTableEntries); // number of sync frames 2152050b28a593350047845a45a14cc5026221ac1620James Dong for (List<int32_t>::iterator it = mStssTableEntries.begin(); 2153050b28a593350047845a45a14cc5026221ac1620James Dong it != mStssTableEntries.end(); ++it) { 2154050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->writeInt32(*it); 2155050b28a593350047845a45a14cc5026221ac1620James Dong } 2156050b28a593350047845a45a14cc5026221ac1620James Dong mOwner->endBox(); // stss 2157050b28a593350047845a45a14cc5026221ac1620James Dong } 2158050b28a593350047845a45a14cc5026221ac1620James Dong 215920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsz"); 216020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 2161be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (mSamplesHaveSameSize) { 21628644c14618d30d9e57a69df40ed939986ebf02c4James Dong List<size_t>::iterator it = mSampleSizes.begin(); 21638644c14618d30d9e57a69df40ed939986ebf02c4James Dong mOwner->writeInt32(*it); // default sample size 2164be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } else { 2165be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong mOwner->writeInt32(0); 2166be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 2167ff4a7fa411401910e6e5ac88aeb6e0080a8cc8b1James Dong mOwner->writeInt32(mNumSamples); 2168be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong if (!mSamplesHaveSameSize) { 21698644c14618d30d9e57a69df40ed939986ebf02c4James Dong for (List<size_t>::iterator it = mSampleSizes.begin(); 21708644c14618d30d9e57a69df40ed939986ebf02c4James Dong it != mSampleSizes.end(); ++it) { 21718644c14618d30d9e57a69df40ed939986ebf02c4James Dong mOwner->writeInt32(*it); 2172be83c9e8c71ce16c0d0e9ed9df525510a49a541bJames Dong } 217320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 217420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsz 217520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 217620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->beginBox("stsc"); 217720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 21781f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mOwner->writeInt32(mNumStscTableEntries); 217913aec890216948b0c364f8f92792129d0335f506James Dong for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 218013aec890216948b0c364f8f92792129d0335f506James Dong it != mStscTableEntries.end(); ++it) { 218113aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->firstChunk); 218213aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->samplesPerChunk); 218313aec890216948b0c364f8f92792129d0335f506James Dong mOwner->writeInt32(it->sampleDescriptionId); 218420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 218520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stsc 21861acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->beginBox(use32BitOffset? "stco": "co64"); 218720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->writeInt32(0); // version=0, flags=0 21881f90c4b3fda9dbd2824d67fd679f850572f114dcJames Dong mOwner->writeInt32(mNumStcoTableEntries); 218913aec890216948b0c364f8f92792129d0335f506James Dong for (List<off_t>::iterator it = mChunkOffsets.begin(); 219013aec890216948b0c364f8f92792129d0335f506James Dong it != mChunkOffsets.end(); ++it) { 21911acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong if (use32BitOffset) { 21921acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt32(static_cast<int32_t>(*it)); 21931acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } else { 21941acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->writeInt64((*it)); 21951acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong } 219620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21978f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mOwner->endBox(); // stco or co64 219820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 219920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // stbl 22001acfe8649f8169caf2ff098c2dc2de880d9a3760James Dong mOwner->endBox(); // minf 220120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // mdia 220220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mOwner->endBox(); // trak 220320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 220420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 220520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 2206