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(const char *path, OutputFormat format)
42343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih    : mFormat(format),
43343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih      mState(UNINITIALIZED) {
44afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui    if (format == OUTPUT_FORMAT_MPEG_4) {
45afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui        mWriter = new MPEG4Writer(path);
46343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih    } else if (format == OUTPUT_FORMAT_WEBM) {
47343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih        mWriter = new WebmWriter(path);
48343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih    }
49343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih
50343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih    if (mWriter != NULL) {
5111287471298193ff51ffb429686f5d63a84a621bztenghui        mFileMeta = new MetaData;
5211287471298193ff51ffb429686f5d63a84a621bztenghui        mState = INITIALIZED;
53afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui    }
546269d53cce5c1c9350565d3d72d92116594260cbztenghui}
556269d53cce5c1c9350565d3d72d92116594260cbztenghui
56afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghuiMediaMuxer::MediaMuxer(int fd, OutputFormat format)
57343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih    : mFormat(format),
58343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih      mState(UNINITIALIZED) {
59afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui    if (format == OUTPUT_FORMAT_MPEG_4) {
60afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui        mWriter = new MPEG4Writer(fd);
61343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih    } else if (format == OUTPUT_FORMAT_WEBM) {
62343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih        mWriter = new WebmWriter(fd);
63343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih    }
64343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih
65343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih    if (mWriter != NULL) {
6611287471298193ff51ffb429686f5d63a84a621bztenghui        mFileMeta = new MetaData;
6711287471298193ff51ffb429686f5d63a84a621bztenghui        mState = INITIALIZED;
68afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui    }
696269d53cce5c1c9350565d3d72d92116594260cbztenghui}
706269d53cce5c1c9350565d3d72d92116594260cbztenghui
716269d53cce5c1c9350565d3d72d92116594260cbztenghuiMediaMuxer::~MediaMuxer() {
726269d53cce5c1c9350565d3d72d92116594260cbztenghui    Mutex::Autolock autoLock(mMuxerLock);
736269d53cce5c1c9350565d3d72d92116594260cbztenghui
746269d53cce5c1c9350565d3d72d92116594260cbztenghui    // Clean up all the internal resources.
7511287471298193ff51ffb429686f5d63a84a621bztenghui    mFileMeta.clear();
766269d53cce5c1c9350565d3d72d92116594260cbztenghui    mWriter.clear();
776269d53cce5c1c9350565d3d72d92116594260cbztenghui    mTrackList.clear();
786269d53cce5c1c9350565d3d72d92116594260cbztenghui}
796269d53cce5c1c9350565d3d72d92116594260cbztenghui
806269d53cce5c1c9350565d3d72d92116594260cbztenghuissize_t MediaMuxer::addTrack(const sp<AMessage> &format) {
816269d53cce5c1c9350565d3d72d92116594260cbztenghui    Mutex::Autolock autoLock(mMuxerLock);
826269d53cce5c1c9350565d3d72d92116594260cbztenghui
836269d53cce5c1c9350565d3d72d92116594260cbztenghui    if (format.get() == NULL) {
846269d53cce5c1c9350565d3d72d92116594260cbztenghui        ALOGE("addTrack() get a null format");
856269d53cce5c1c9350565d3d72d92116594260cbztenghui        return -EINVAL;
866269d53cce5c1c9350565d3d72d92116594260cbztenghui    }
876269d53cce5c1c9350565d3d72d92116594260cbztenghui
8811287471298193ff51ffb429686f5d63a84a621bztenghui    if (mState != INITIALIZED) {
896269d53cce5c1c9350565d3d72d92116594260cbztenghui        ALOGE("addTrack() must be called after constructor and before start().");
906269d53cce5c1c9350565d3d72d92116594260cbztenghui        return INVALID_OPERATION;
916269d53cce5c1c9350565d3d72d92116594260cbztenghui    }
926269d53cce5c1c9350565d3d72d92116594260cbztenghui
9311287471298193ff51ffb429686f5d63a84a621bztenghui    sp<MetaData> trackMeta = new MetaData;
9411287471298193ff51ffb429686f5d63a84a621bztenghui    convertMessageToMetaData(format, trackMeta);
956269d53cce5c1c9350565d3d72d92116594260cbztenghui
9611287471298193ff51ffb429686f5d63a84a621bztenghui    sp<MediaAdapter> newTrack = new MediaAdapter(trackMeta);
975883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong    status_t result = mWriter->addSource(newTrack);
985883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong    if (result == OK) {
995883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong        return mTrackList.add(newTrack);
1005883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong    }
1015883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong    return -1;
1026269d53cce5c1c9350565d3d72d92116594260cbztenghui}
1036269d53cce5c1c9350565d3d72d92116594260cbztenghui
10411287471298193ff51ffb429686f5d63a84a621bztenghuistatus_t MediaMuxer::setOrientationHint(int degrees) {
10511287471298193ff51ffb429686f5d63a84a621bztenghui    Mutex::Autolock autoLock(mMuxerLock);
10611287471298193ff51ffb429686f5d63a84a621bztenghui    if (mState != INITIALIZED) {
10711287471298193ff51ffb429686f5d63a84a621bztenghui        ALOGE("setOrientationHint() must be called before start().");
10811287471298193ff51ffb429686f5d63a84a621bztenghui        return INVALID_OPERATION;
10911287471298193ff51ffb429686f5d63a84a621bztenghui    }
11011287471298193ff51ffb429686f5d63a84a621bztenghui
11111287471298193ff51ffb429686f5d63a84a621bztenghui    if (degrees != 0 && degrees != 90 && degrees != 180 && degrees != 270) {
11211287471298193ff51ffb429686f5d63a84a621bztenghui        ALOGE("setOrientationHint() get invalid degrees");
11311287471298193ff51ffb429686f5d63a84a621bztenghui        return -EINVAL;
11411287471298193ff51ffb429686f5d63a84a621bztenghui    }
11511287471298193ff51ffb429686f5d63a84a621bztenghui
11611287471298193ff51ffb429686f5d63a84a621bztenghui    mFileMeta->setInt32(kKeyRotation, degrees);
11711287471298193ff51ffb429686f5d63a84a621bztenghui    return OK;
11811287471298193ff51ffb429686f5d63a84a621bztenghui}
11911287471298193ff51ffb429686f5d63a84a621bztenghui
1207f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun Hestatus_t MediaMuxer::setLocation(int latitude, int longitude) {
1217f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He    Mutex::Autolock autoLock(mMuxerLock);
1227f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He    if (mState != INITIALIZED) {
1237f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He        ALOGE("setLocation() must be called before start().");
1247f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He        return INVALID_OPERATION;
1257f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He    }
126343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih    if (mFormat != OUTPUT_FORMAT_MPEG_4) {
127343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih        ALOGE("setLocation() is only supported for .mp4 output.");
128343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih        return INVALID_OPERATION;
129343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih    }
130343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih
1317f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He    ALOGV("Setting location: latitude = %d, longitude = %d", latitude, longitude);
132343947abc8b7c126f966fd32a0b18bff6c2cecd1Robert Shih    return static_cast<MPEG4Writer*>(mWriter.get())->setGeoData(latitude, longitude);
1337f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He}
1347f9551f75eedb3e4e1fe8feaaba48d8080635fc4Zhijun He
1356269d53cce5c1c9350565d3d72d92116594260cbztenghuistatus_t MediaMuxer::start() {
1366269d53cce5c1c9350565d3d72d92116594260cbztenghui    Mutex::Autolock autoLock(mMuxerLock);
13711287471298193ff51ffb429686f5d63a84a621bztenghui    if (mState == INITIALIZED) {
1386269d53cce5c1c9350565d3d72d92116594260cbztenghui        mState = STARTED;
139e756d9753c7cffe2e9731a31fa98a3e8f37151c9ztenghui        mFileMeta->setInt32(kKeyRealTimeRecording, false);
14011287471298193ff51ffb429686f5d63a84a621bztenghui        return mWriter->start(mFileMeta.get());
1416269d53cce5c1c9350565d3d72d92116594260cbztenghui    } else {
1426269d53cce5c1c9350565d3d72d92116594260cbztenghui        ALOGE("start() is called in invalid state %d", mState);
1436269d53cce5c1c9350565d3d72d92116594260cbztenghui        return INVALID_OPERATION;
1446269d53cce5c1c9350565d3d72d92116594260cbztenghui    }
1456269d53cce5c1c9350565d3d72d92116594260cbztenghui}
1466269d53cce5c1c9350565d3d72d92116594260cbztenghui
1476269d53cce5c1c9350565d3d72d92116594260cbztenghuistatus_t MediaMuxer::stop() {
1486269d53cce5c1c9350565d3d72d92116594260cbztenghui    Mutex::Autolock autoLock(mMuxerLock);
1496269d53cce5c1c9350565d3d72d92116594260cbztenghui
1506269d53cce5c1c9350565d3d72d92116594260cbztenghui    if (mState == STARTED) {
1516269d53cce5c1c9350565d3d72d92116594260cbztenghui        mState = STOPPED;
1526269d53cce5c1c9350565d3d72d92116594260cbztenghui        for (size_t i = 0; i < mTrackList.size(); i++) {
1535883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong            if (mTrackList[i]->stop() != OK) {
1545883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong                return INVALID_OPERATION;
1555883d53cf8300d8b13a1a6ef3310d72a55e191c0James Dong            }
1566269d53cce5c1c9350565d3d72d92116594260cbztenghui        }
1576269d53cce5c1c9350565d3d72d92116594260cbztenghui        return mWriter->stop();
1586269d53cce5c1c9350565d3d72d92116594260cbztenghui    } else {
1596269d53cce5c1c9350565d3d72d92116594260cbztenghui        ALOGE("stop() is called in invalid state %d", mState);
1606269d53cce5c1c9350565d3d72d92116594260cbztenghui        return INVALID_OPERATION;
1616269d53cce5c1c9350565d3d72d92116594260cbztenghui    }
1626269d53cce5c1c9350565d3d72d92116594260cbztenghui}
1636269d53cce5c1c9350565d3d72d92116594260cbztenghui
1646269d53cce5c1c9350565d3d72d92116594260cbztenghuistatus_t MediaMuxer::writeSampleData(const sp<ABuffer> &buffer, size_t trackIndex,
1656269d53cce5c1c9350565d3d72d92116594260cbztenghui                                     int64_t timeUs, uint32_t flags) {
1666269d53cce5c1c9350565d3d72d92116594260cbztenghui    Mutex::Autolock autoLock(mMuxerLock);
1676269d53cce5c1c9350565d3d72d92116594260cbztenghui
1686269d53cce5c1c9350565d3d72d92116594260cbztenghui    if (buffer.get() == NULL) {
1696269d53cce5c1c9350565d3d72d92116594260cbztenghui        ALOGE("WriteSampleData() get an NULL buffer.");
1706269d53cce5c1c9350565d3d72d92116594260cbztenghui        return -EINVAL;
1716269d53cce5c1c9350565d3d72d92116594260cbztenghui    }
1726269d53cce5c1c9350565d3d72d92116594260cbztenghui
1736269d53cce5c1c9350565d3d72d92116594260cbztenghui    if (mState != STARTED) {
1746269d53cce5c1c9350565d3d72d92116594260cbztenghui        ALOGE("WriteSampleData() is called in invalid state %d", mState);
1756269d53cce5c1c9350565d3d72d92116594260cbztenghui        return INVALID_OPERATION;
1766269d53cce5c1c9350565d3d72d92116594260cbztenghui    }
1776269d53cce5c1c9350565d3d72d92116594260cbztenghui
1786269d53cce5c1c9350565d3d72d92116594260cbztenghui    if (trackIndex >= mTrackList.size()) {
179a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("WriteSampleData() get an invalid index %zu", trackIndex);
1806269d53cce5c1c9350565d3d72d92116594260cbztenghui        return -EINVAL;
1816269d53cce5c1c9350565d3d72d92116594260cbztenghui    }
1826269d53cce5c1c9350565d3d72d92116594260cbztenghui
1836269d53cce5c1c9350565d3d72d92116594260cbztenghui    MediaBuffer* mediaBuffer = new MediaBuffer(buffer);
1846269d53cce5c1c9350565d3d72d92116594260cbztenghui
1856269d53cce5c1c9350565d3d72d92116594260cbztenghui    mediaBuffer->add_ref(); // Released in MediaAdapter::signalBufferReturned().
1866269d53cce5c1c9350565d3d72d92116594260cbztenghui    mediaBuffer->set_range(buffer->offset(), buffer->size());
1876269d53cce5c1c9350565d3d72d92116594260cbztenghui
18811287471298193ff51ffb429686f5d63a84a621bztenghui    sp<MetaData> sampleMetaData = mediaBuffer->meta_data();
18911287471298193ff51ffb429686f5d63a84a621bztenghui    sampleMetaData->setInt64(kKeyTime, timeUs);
1906269d53cce5c1c9350565d3d72d92116594260cbztenghui    // Just set the kKeyDecodingTime as the presentation time for now.
19111287471298193ff51ffb429686f5d63a84a621bztenghui    sampleMetaData->setInt64(kKeyDecodingTime, timeUs);
1926269d53cce5c1c9350565d3d72d92116594260cbztenghui
1936f505a4c0b91d88d2759fbd7e17d91f3ed715165Lajos Molnar    if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
19411287471298193ff51ffb429686f5d63a84a621bztenghui        sampleMetaData->setInt32(kKeyIsSyncFrame, true);
1956269d53cce5c1c9350565d3d72d92116594260cbztenghui    }
1966269d53cce5c1c9350565d3d72d92116594260cbztenghui
197afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui    sp<MediaAdapter> currentTrack = mTrackList[trackIndex];
1986269d53cce5c1c9350565d3d72d92116594260cbztenghui    // This pushBuffer will wait until the mediaBuffer is consumed.
1996269d53cce5c1c9350565d3d72d92116594260cbztenghui    return currentTrack->pushBuffer(mediaBuffer);
2006269d53cce5c1c9350565d3d72d92116594260cbztenghui}
2016269d53cce5c1c9350565d3d72d92116594260cbztenghui
2026269d53cce5c1c9350565d3d72d92116594260cbztenghui}  // namespace android
203