MediaMuxer.cpp revision afde4e56566af19b36f1fe5e7aa7f226bf1703dd
1/* 2 * Copyright 2013, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "MediaMuxer" 19#include <utils/Log.h> 20 21#include <media/stagefright/MediaMuxer.h> 22 23#include <media/stagefright/foundation/ABuffer.h> 24#include <media/stagefright/foundation/ADebug.h> 25#include <media/stagefright/foundation/AMessage.h> 26#include <media/stagefright/MediaAdapter.h> 27#include <media/stagefright/MediaBuffer.h> 28#include <media/stagefright/MediaCodec.h> 29#include <media/stagefright/MediaDefs.h> 30#include <media/stagefright/MediaErrors.h> 31#include <media/stagefright/MediaSource.h> 32#include <media/stagefright/MetaData.h> 33#include <media/stagefright/MPEG4Writer.h> 34#include <media/stagefright/Utils.h> 35 36namespace android { 37 38MediaMuxer::MediaMuxer(const char *path, OutputFormat format) 39 : mState(UNINITED) { 40 if (format == OUTPUT_FORMAT_MPEG_4) { 41 mWriter = new MPEG4Writer(path); 42 mState = INITED; 43 } 44} 45 46MediaMuxer::MediaMuxer(int fd, OutputFormat format) 47 : mState(UNINITED) { 48 if (format == OUTPUT_FORMAT_MPEG_4) { 49 mWriter = new MPEG4Writer(fd); 50 mState = INITED; 51 } 52} 53 54MediaMuxer::~MediaMuxer() { 55 Mutex::Autolock autoLock(mMuxerLock); 56 57 // Clean up all the internal resources. 58 mWriter.clear(); 59 mTrackList.clear(); 60} 61 62ssize_t MediaMuxer::addTrack(const sp<AMessage> &format) { 63 Mutex::Autolock autoLock(mMuxerLock); 64 65 if (format.get() == NULL) { 66 ALOGE("addTrack() get a null format"); 67 return -EINVAL; 68 } 69 70 if (mState != INITED) { 71 ALOGE("addTrack() must be called after constructor and before start()."); 72 return INVALID_OPERATION; 73 } 74 75 sp<MetaData> meta = new MetaData; 76 convertMessageToMetaData(format, meta); 77 78 sp<MediaAdapter> newTrack = new MediaAdapter(meta); 79 return mTrackList.add(newTrack); 80} 81 82status_t MediaMuxer::start() { 83 Mutex::Autolock autoLock(mMuxerLock); 84 85 if (mState == INITED) { 86 mState = STARTED; 87 for (size_t i = 0 ; i < mTrackList.size(); i++) { 88 mWriter->addSource(mTrackList[i]); 89 } 90 return mWriter->start(); 91 } else { 92 ALOGE("start() is called in invalid state %d", mState); 93 return INVALID_OPERATION; 94 } 95} 96 97status_t MediaMuxer::stop() { 98 Mutex::Autolock autoLock(mMuxerLock); 99 100 if (mState == STARTED) { 101 mState = STOPPED; 102 for (size_t i = 0; i < mTrackList.size(); i++) { 103 mTrackList[i]->stop(); 104 } 105 return mWriter->stop(); 106 } else { 107 ALOGE("stop() is called in invalid state %d", mState); 108 return INVALID_OPERATION; 109 } 110} 111 112status_t MediaMuxer::writeSampleData(const sp<ABuffer> &buffer, size_t trackIndex, 113 int64_t timeUs, uint32_t flags) { 114 Mutex::Autolock autoLock(mMuxerLock); 115 116 if (buffer.get() == NULL) { 117 ALOGE("WriteSampleData() get an NULL buffer."); 118 return -EINVAL; 119 } 120 121 if (mState != STARTED) { 122 ALOGE("WriteSampleData() is called in invalid state %d", mState); 123 return INVALID_OPERATION; 124 } 125 126 if (trackIndex >= mTrackList.size()) { 127 ALOGE("WriteSampleData() get an invalid index %d", trackIndex); 128 return -EINVAL; 129 } 130 131 MediaBuffer* mediaBuffer = new MediaBuffer(buffer); 132 133 mediaBuffer->add_ref(); // Released in MediaAdapter::signalBufferReturned(). 134 mediaBuffer->set_range(buffer->offset(), buffer->size()); 135 136 sp<MetaData> metaData = mediaBuffer->meta_data(); 137 metaData->setInt64(kKeyTime, timeUs); 138 // Just set the kKeyDecodingTime as the presentation time for now. 139 metaData->setInt64(kKeyDecodingTime, timeUs); 140 141 if (flags & SAMPLE_FLAG_SYNC) { 142 metaData->setInt32(kKeyIsSyncFrame, true); 143 } 144 145 sp<MediaAdapter> currentTrack = mTrackList[trackIndex]; 146 // This pushBuffer will wait until the mediaBuffer is consumed. 147 return currentTrack->pushBuffer(mediaBuffer); 148} 149 150} // namespace android 151