16269d53cce5c1c9350565d3d72d92116594260cbztenghui/* 26269d53cce5c1c9350565d3d72d92116594260cbztenghui * Copyright 2013, The Android Open Source Project 36269d53cce5c1c9350565d3d72d92116594260cbztenghui * 46269d53cce5c1c9350565d3d72d92116594260cbztenghui * Licensed under the Apache License, Version 2.0 (the "License"); 56269d53cce5c1c9350565d3d72d92116594260cbztenghui * you may not use this file except in compliance with the License. 66269d53cce5c1c9350565d3d72d92116594260cbztenghui * You may obtain a copy of the License at 76269d53cce5c1c9350565d3d72d92116594260cbztenghui * 86269d53cce5c1c9350565d3d72d92116594260cbztenghui * http://www.apache.org/licenses/LICENSE-2.0 96269d53cce5c1c9350565d3d72d92116594260cbztenghui * 106269d53cce5c1c9350565d3d72d92116594260cbztenghui * Unless required by applicable law or agreed to in writing, software 116269d53cce5c1c9350565d3d72d92116594260cbztenghui * distributed under the License is distributed on an "AS IS" BASIS, 126269d53cce5c1c9350565d3d72d92116594260cbztenghui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136269d53cce5c1c9350565d3d72d92116594260cbztenghui * See the License for the specific language governing permissions and 146269d53cce5c1c9350565d3d72d92116594260cbztenghui * limitations under the License. 156269d53cce5c1c9350565d3d72d92116594260cbztenghui */ 166269d53cce5c1c9350565d3d72d92116594260cbztenghui 176269d53cce5c1c9350565d3d72d92116594260cbztenghui//#define LOG_NDEBUG 0 186269d53cce5c1c9350565d3d72d92116594260cbztenghui#define LOG_TAG "MediaMuxer" 19343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih 20343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih#include "webm/WebmWriter.h" 21343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih 226269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <utils/Log.h> 236269d53cce5c1c9350565d3d72d92116594260cbztenghui 246269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/MediaMuxer.h> 256269d53cce5c1c9350565d3d72d92116594260cbztenghui 266269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/foundation/ABuffer.h> 276269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/foundation/ADebug.h> 286269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/foundation/AMessage.h> 296269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/MediaAdapter.h> 306269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/MediaBuffer.h> 316269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/MediaCodec.h> 326269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/MediaDefs.h> 336269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/MediaErrors.h> 346269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/MediaSource.h> 356269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/MetaData.h> 366269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/MPEG4Writer.h> 376269d53cce5c1c9350565d3d72d92116594260cbztenghui#include <media/stagefright/Utils.h> 386269d53cce5c1c9350565d3d72d92116594260cbztenghui 396269d53cce5c1c9350565d3d72d92116594260cbztenghuinamespace android { 406269d53cce5c1c9350565d3d72d92116594260cbztenghui 41afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghuiMediaMuxer::MediaMuxer(int fd, OutputFormat format) 42343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih : mFormat(format), 43343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih mState(UNINITIALIZED) { 44afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui if (format == OUTPUT_FORMAT_MPEG_4) { 45afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui mWriter = new MPEG4Writer(fd); 46343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih } else if (format == OUTPUT_FORMAT_WEBM) { 47343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih mWriter = new WebmWriter(fd); 48343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih } 49343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih 50343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih if (mWriter != NULL) { 5111287471298193ff51ffb429686f5d63a84a621bztenghui mFileMeta = new MetaData; 5211287471298193ff51ffb429686f5d63a84a621bztenghui mState = INITIALIZED; 53afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui } 546269d53cce5c1c9350565d3d72d92116594260cbztenghui} 556269d53cce5c1c9350565d3d72d92116594260cbztenghui 566269d53cce5c1c9350565d3d72d92116594260cbztenghuiMediaMuxer::~MediaMuxer() { 576269d53cce5c1c9350565d3d72d92116594260cbztenghui Mutex::Autolock autoLock(mMuxerLock); 586269d53cce5c1c9350565d3d72d92116594260cbztenghui 596269d53cce5c1c9350565d3d72d92116594260cbztenghui // Clean up all the internal resources. 6011287471298193ff51ffb429686f5d63a84a621bztenghui mFileMeta.clear(); 616269d53cce5c1c9350565d3d72d92116594260cbztenghui mWriter.clear(); 626269d53cce5c1c9350565d3d72d92116594260cbztenghui mTrackList.clear(); 636269d53cce5c1c9350565d3d72d92116594260cbztenghui} 646269d53cce5c1c9350565d3d72d92116594260cbztenghui 656269d53cce5c1c9350565d3d72d92116594260cbztenghuissize_t MediaMuxer::addTrack(const sp<AMessage> &format) { 666269d53cce5c1c9350565d3d72d92116594260cbztenghui Mutex::Autolock autoLock(mMuxerLock); 676269d53cce5c1c9350565d3d72d92116594260cbztenghui 686269d53cce5c1c9350565d3d72d92116594260cbztenghui if (format.get() == NULL) { 696269d53cce5c1c9350565d3d72d92116594260cbztenghui ALOGE("addTrack() get a null format"); 706269d53cce5c1c9350565d3d72d92116594260cbztenghui return -EINVAL; 716269d53cce5c1c9350565d3d72d92116594260cbztenghui } 726269d53cce5c1c9350565d3d72d92116594260cbztenghui 7311287471298193ff51ffb429686f5d63a84a621bztenghui if (mState != INITIALIZED) { 746269d53cce5c1c9350565d3d72d92116594260cbztenghui ALOGE("addTrack() must be called after constructor and before start()."); 756269d53cce5c1c9350565d3d72d92116594260cbztenghui return INVALID_OPERATION; 766269d53cce5c1c9350565d3d72d92116594260cbztenghui } 776269d53cce5c1c9350565d3d72d92116594260cbztenghui 7811287471298193ff51ffb429686f5d63a84a621bztenghui sp<MetaData> trackMeta = new MetaData; 7911287471298193ff51ffb429686f5d63a84a621bztenghui convertMessageToMetaData(format, trackMeta); 806269d53cce5c1c9350565d3d72d92116594260cbztenghui 8111287471298193ff51ffb429686f5d63a84a621bztenghui sp<MediaAdapter> newTrack = new MediaAdapter(trackMeta); 825883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong status_t result = mWriter->addSource(newTrack); 835883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong if (result == OK) { 845883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong return mTrackList.add(newTrack); 855883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong } 865883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong return -1; 876269d53cce5c1c9350565d3d72d92116594260cbztenghui} 886269d53cce5c1c9350565d3d72d92116594260cbztenghui 8911287471298193ff51ffb429686f5d63a84a621bztenghuistatus_t MediaMuxer::setOrientationHint(int degrees) { 9011287471298193ff51ffb429686f5d63a84a621bztenghui Mutex::Autolock autoLock(mMuxerLock); 9111287471298193ff51ffb429686f5d63a84a621bztenghui if (mState != INITIALIZED) { 9211287471298193ff51ffb429686f5d63a84a621bztenghui ALOGE("setOrientationHint() must be called before start()."); 9311287471298193ff51ffb429686f5d63a84a621bztenghui return INVALID_OPERATION; 9411287471298193ff51ffb429686f5d63a84a621bztenghui } 9511287471298193ff51ffb429686f5d63a84a621bztenghui 9611287471298193ff51ffb429686f5d63a84a621bztenghui if (degrees != 0 && degrees != 90 && degrees != 180 && degrees != 270) { 9711287471298193ff51ffb429686f5d63a84a621bztenghui ALOGE("setOrientationHint() get invalid degrees"); 9811287471298193ff51ffb429686f5d63a84a621bztenghui return -EINVAL; 9911287471298193ff51ffb429686f5d63a84a621bztenghui } 10011287471298193ff51ffb429686f5d63a84a621bztenghui 10111287471298193ff51ffb429686f5d63a84a621bztenghui mFileMeta->setInt32(kKeyRotation, degrees); 10211287471298193ff51ffb429686f5d63a84a621bztenghui return OK; 10311287471298193ff51ffb429686f5d63a84a621bztenghui} 10411287471298193ff51ffb429686f5d63a84a621bztenghui 1057f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun Hestatus_t MediaMuxer::setLocation(int latitude, int longitude) { 1067f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He Mutex::Autolock autoLock(mMuxerLock); 1077f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He if (mState != INITIALIZED) { 1087f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He ALOGE("setLocation() must be called before start()."); 1097f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He return INVALID_OPERATION; 1107f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He } 111343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih if (mFormat != OUTPUT_FORMAT_MPEG_4) { 112343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih ALOGE("setLocation() is only supported for .mp4 output."); 113343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih return INVALID_OPERATION; 114343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih } 115343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih 1167f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He ALOGV("Setting location: latitude = %d, longitude = %d", latitude, longitude); 117343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih return static_cast<MPEG4Writer*>(mWriter.get())->setGeoData(latitude, longitude); 1187f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He} 1197f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He 1206269d53cce5c1c9350565d3d72d92116594260cbztenghuistatus_t MediaMuxer::start() { 1216269d53cce5c1c9350565d3d72d92116594260cbztenghui Mutex::Autolock autoLock(mMuxerLock); 12211287471298193ff51ffb429686f5d63a84a621bztenghui if (mState == INITIALIZED) { 1236269d53cce5c1c9350565d3d72d92116594260cbztenghui mState = STARTED; 124e756d9753c7cffe2e9731a31fa98a3e8f37151c9ztenghui mFileMeta->setInt32(kKeyRealTimeRecording, false); 12511287471298193ff51ffb429686f5d63a84a621bztenghui return mWriter->start(mFileMeta.get()); 1266269d53cce5c1c9350565d3d72d92116594260cbztenghui } else { 1276269d53cce5c1c9350565d3d72d92116594260cbztenghui ALOGE("start() is called in invalid state %d", mState); 1286269d53cce5c1c9350565d3d72d92116594260cbztenghui return INVALID_OPERATION; 1296269d53cce5c1c9350565d3d72d92116594260cbztenghui } 1306269d53cce5c1c9350565d3d72d92116594260cbztenghui} 1316269d53cce5c1c9350565d3d72d92116594260cbztenghui 1326269d53cce5c1c9350565d3d72d92116594260cbztenghuistatus_t MediaMuxer::stop() { 1336269d53cce5c1c9350565d3d72d92116594260cbztenghui Mutex::Autolock autoLock(mMuxerLock); 1346269d53cce5c1c9350565d3d72d92116594260cbztenghui 1356269d53cce5c1c9350565d3d72d92116594260cbztenghui if (mState == STARTED) { 1366269d53cce5c1c9350565d3d72d92116594260cbztenghui mState = STOPPED; 1376269d53cce5c1c9350565d3d72d92116594260cbztenghui for (size_t i = 0; i < mTrackList.size(); i++) { 1385883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong if (mTrackList[i]->stop() != OK) { 1395883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong return INVALID_OPERATION; 1405883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong } 1416269d53cce5c1c9350565d3d72d92116594260cbztenghui } 1426269d53cce5c1c9350565d3d72d92116594260cbztenghui return mWriter->stop(); 1436269d53cce5c1c9350565d3d72d92116594260cbztenghui } else { 1446269d53cce5c1c9350565d3d72d92116594260cbztenghui ALOGE("stop() is called in invalid state %d", mState); 1456269d53cce5c1c9350565d3d72d92116594260cbztenghui return INVALID_OPERATION; 1466269d53cce5c1c9350565d3d72d92116594260cbztenghui } 1476269d53cce5c1c9350565d3d72d92116594260cbztenghui} 1486269d53cce5c1c9350565d3d72d92116594260cbztenghui 1496269d53cce5c1c9350565d3d72d92116594260cbztenghuistatus_t MediaMuxer::writeSampleData(const sp<ABuffer> &buffer, size_t trackIndex, 1506269d53cce5c1c9350565d3d72d92116594260cbztenghui int64_t timeUs, uint32_t flags) { 1516269d53cce5c1c9350565d3d72d92116594260cbztenghui Mutex::Autolock autoLock(mMuxerLock); 1526269d53cce5c1c9350565d3d72d92116594260cbztenghui 1536269d53cce5c1c9350565d3d72d92116594260cbztenghui if (buffer.get() == NULL) { 1546269d53cce5c1c9350565d3d72d92116594260cbztenghui ALOGE("WriteSampleData() get an NULL buffer."); 1556269d53cce5c1c9350565d3d72d92116594260cbztenghui return -EINVAL; 1566269d53cce5c1c9350565d3d72d92116594260cbztenghui } 1576269d53cce5c1c9350565d3d72d92116594260cbztenghui 1586269d53cce5c1c9350565d3d72d92116594260cbztenghui if (mState != STARTED) { 1596269d53cce5c1c9350565d3d72d92116594260cbztenghui ALOGE("WriteSampleData() is called in invalid state %d", mState); 1606269d53cce5c1c9350565d3d72d92116594260cbztenghui return INVALID_OPERATION; 1616269d53cce5c1c9350565d3d72d92116594260cbztenghui } 1626269d53cce5c1c9350565d3d72d92116594260cbztenghui 1636269d53cce5c1c9350565d3d72d92116594260cbztenghui if (trackIndex >= mTrackList.size()) { 164a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGE("WriteSampleData() get an invalid index %zu", trackIndex); 1656269d53cce5c1c9350565d3d72d92116594260cbztenghui return -EINVAL; 1666269d53cce5c1c9350565d3d72d92116594260cbztenghui } 1676269d53cce5c1c9350565d3d72d92116594260cbztenghui 1686269d53cce5c1c9350565d3d72d92116594260cbztenghui MediaBuffer* mediaBuffer = new MediaBuffer(buffer); 1696269d53cce5c1c9350565d3d72d92116594260cbztenghui 1706269d53cce5c1c9350565d3d72d92116594260cbztenghui mediaBuffer->add_ref(); // Released in MediaAdapter::signalBufferReturned(). 1716269d53cce5c1c9350565d3d72d92116594260cbztenghui mediaBuffer->set_range(buffer->offset(), buffer->size()); 1726269d53cce5c1c9350565d3d72d92116594260cbztenghui 17311287471298193ff51ffb429686f5d63a84a621bztenghui sp<MetaData> sampleMetaData = mediaBuffer->meta_data(); 17411287471298193ff51ffb429686f5d63a84a621bztenghui sampleMetaData->setInt64(kKeyTime, timeUs); 1756269d53cce5c1c9350565d3d72d92116594260cbztenghui // Just set the kKeyDecodingTime as the presentation time for now. 17611287471298193ff51ffb429686f5d63a84a621bztenghui sampleMetaData->setInt64(kKeyDecodingTime, timeUs); 1776269d53cce5c1c9350565d3d72d92116594260cbztenghui 1786f505a4c0b91d88d2759fbd7e17d91f3ed715165Lajos Molnar if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) { 17911287471298193ff51ffb429686f5d63a84a621bztenghui sampleMetaData->setInt32(kKeyIsSyncFrame, true); 1806269d53cce5c1c9350565d3d72d92116594260cbztenghui } 1816269d53cce5c1c9350565d3d72d92116594260cbztenghui 182afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui sp<MediaAdapter> currentTrack = mTrackList[trackIndex]; 1836269d53cce5c1c9350565d3d72d92116594260cbztenghui // This pushBuffer will wait until the mediaBuffer is consumed. 1846269d53cce5c1c9350565d3d72d92116594260cbztenghui return currentTrack->pushBuffer(mediaBuffer); 1856269d53cce5c1c9350565d3d72d92116594260cbztenghui} 1866269d53cce5c1c9350565d3d72d92116594260cbztenghui 1876269d53cce5c1c9350565d3d72d92116594260cbztenghui} // namespace android 188