muxer.cpp revision 377b2ec9a2885f9b6405b07ba900a9e3f4349c38
1fc9afba35492257e5e80a36b0765ff035908bb6dztenghui/* 2fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * Copyright (C) 2013 The Android Open Source Project 3fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * 4fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * Licensed under the Apache License, Version 2.0 (the "License"); 5fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * you may not use this file except in compliance with the License. 6fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * You may obtain a copy of the License at 7fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * 8fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * http://www.apache.org/licenses/LICENSE-2.0 9fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * 10fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * Unless required by applicable law or agreed to in writing, software 11fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * distributed under the License is distributed on an "AS IS" BASIS, 12fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * See the License for the specific language governing permissions and 14fc9afba35492257e5e80a36b0765ff035908bb6dztenghui * limitations under the License. 15fc9afba35492257e5e80a36b0765ff035908bb6dztenghui */ 16fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 17fc9afba35492257e5e80a36b0765ff035908bb6dztenghui//#define LOG_NDEBUG 0 18fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#define LOG_TAG "muxer" 19377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT#include <inttypes.h> 20fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <utils/Log.h> 21fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 22fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <binder/ProcessState.h> 23fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <media/stagefright/foundation/ABuffer.h> 24fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <media/stagefright/foundation/ADebug.h> 25fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <media/stagefright/foundation/ALooper.h> 26fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <media/stagefright/foundation/AMessage.h> 27fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <media/stagefright/foundation/AString.h> 28fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <media/stagefright/DataSource.h> 29fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <media/stagefright/MediaCodec.h> 30fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <media/stagefright/MediaDefs.h> 31fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <media/stagefright/MediaMuxer.h> 32fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <media/stagefright/MetaData.h> 33fc9afba35492257e5e80a36b0765ff035908bb6dztenghui#include <media/stagefright/NuMediaExtractor.h> 34fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 35fc9afba35492257e5e80a36b0765ff035908bb6dztenghuistatic void usage(const char *me) { 36fc9afba35492257e5e80a36b0765ff035908bb6dztenghui fprintf(stderr, "usage: %s [-a] [-v] [-s <trim start time>]" 37fc9afba35492257e5e80a36b0765ff035908bb6dztenghui " [-e <trim end time>] [-o <output file>]" 38fc9afba35492257e5e80a36b0765ff035908bb6dztenghui " <input video file>\n", me); 39fc9afba35492257e5e80a36b0765ff035908bb6dztenghui fprintf(stderr, " -h help\n"); 40fc9afba35492257e5e80a36b0765ff035908bb6dztenghui fprintf(stderr, " -a use audio\n"); 41fc9afba35492257e5e80a36b0765ff035908bb6dztenghui fprintf(stderr, " -v use video\n"); 42fc9afba35492257e5e80a36b0765ff035908bb6dztenghui fprintf(stderr, " -s Time in milli-seconds when the trim should start\n"); 43fc9afba35492257e5e80a36b0765ff035908bb6dztenghui fprintf(stderr, " -e Time in milli-seconds when the trim should end\n"); 44fc9afba35492257e5e80a36b0765ff035908bb6dztenghui fprintf(stderr, " -o output file name. Default is /sdcard/muxeroutput.mp4\n"); 45fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 46fc9afba35492257e5e80a36b0765ff035908bb6dztenghui exit(1); 47fc9afba35492257e5e80a36b0765ff035908bb6dztenghui} 48fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 49fc9afba35492257e5e80a36b0765ff035908bb6dztenghuiusing namespace android; 50fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 51fc9afba35492257e5e80a36b0765ff035908bb6dztenghuistatic int muxing( 52fc9afba35492257e5e80a36b0765ff035908bb6dztenghui const android::sp<android::ALooper> &looper, 53fc9afba35492257e5e80a36b0765ff035908bb6dztenghui const char *path, 54fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bool useAudio, 55fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bool useVideo, 56fc9afba35492257e5e80a36b0765ff035908bb6dztenghui const char *outputFileName, 57fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bool enableTrim, 58fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int trimStartTimeMs, 5911287471298193ff51ffb429686f5d63a84a621bztenghui int trimEndTimeMs, 6011287471298193ff51ffb429686f5d63a84a621bztenghui int rotationDegrees) { 61fc9afba35492257e5e80a36b0765ff035908bb6dztenghui sp<NuMediaExtractor> extractor = new NuMediaExtractor; 62fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (extractor->setDataSource(path) != OK) { 63fc9afba35492257e5e80a36b0765ff035908bb6dztenghui fprintf(stderr, "unable to instantiate extractor. %s\n", path); 64fc9afba35492257e5e80a36b0765ff035908bb6dztenghui return 1; 65fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 66fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 67fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (outputFileName == NULL) { 68fc9afba35492257e5e80a36b0765ff035908bb6dztenghui outputFileName = "/sdcard/muxeroutput.mp4"; 69fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 70fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 71fc9afba35492257e5e80a36b0765ff035908bb6dztenghui ALOGV("input file %s, output file %s", path, outputFileName); 72fc9afba35492257e5e80a36b0765ff035908bb6dztenghui ALOGV("useAudio %d, useVideo %d", useAudio, useVideo); 73fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 74afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui sp<MediaMuxer> muxer = new MediaMuxer(outputFileName, 75afde4e56566af19b36f1fe5e7aa7f226bf1703ddztenghui MediaMuxer::OUTPUT_FORMAT_MPEG_4); 76fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 77fc9afba35492257e5e80a36b0765ff035908bb6dztenghui size_t trackCount = extractor->countTracks(); 78fc9afba35492257e5e80a36b0765ff035908bb6dztenghui // Map the extractor's track index to the muxer's track index. 79fc9afba35492257e5e80a36b0765ff035908bb6dztenghui KeyedVector<size_t, ssize_t> trackIndexMap; 80fc9afba35492257e5e80a36b0765ff035908bb6dztenghui size_t bufferSize = 1 * 1024 * 1024; // default buffer size is 1MB. 81fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 82fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bool haveAudio = false; 83fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bool haveVideo = false; 84fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 85fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int64_t trimStartTimeUs = trimStartTimeMs * 1000; 86fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int64_t trimEndTimeUs = trimEndTimeMs * 1000; 87fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bool trimStarted = false; 88fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int64_t trimOffsetTimeUs = 0; 89fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 90fc9afba35492257e5e80a36b0765ff035908bb6dztenghui for (size_t i = 0; i < trackCount; ++i) { 91fc9afba35492257e5e80a36b0765ff035908bb6dztenghui sp<AMessage> format; 92fc9afba35492257e5e80a36b0765ff035908bb6dztenghui status_t err = extractor->getTrackFormat(i, &format); 93fc9afba35492257e5e80a36b0765ff035908bb6dztenghui CHECK_EQ(err, (status_t)OK); 94fc9afba35492257e5e80a36b0765ff035908bb6dztenghui ALOGV("extractor getTrackFormat: %s", format->debugString().c_str()); 95fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 96fc9afba35492257e5e80a36b0765ff035908bb6dztenghui AString mime; 97fc9afba35492257e5e80a36b0765ff035908bb6dztenghui CHECK(format->findString("mime", &mime)); 98fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 99fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6); 100fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bool isVideo = !strncasecmp(mime.c_str(), "video/", 6); 101fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 102fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (useAudio && !haveAudio && isAudio) { 103fc9afba35492257e5e80a36b0765ff035908bb6dztenghui haveAudio = true; 104fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } else if (useVideo && !haveVideo && isVideo) { 105fc9afba35492257e5e80a36b0765ff035908bb6dztenghui haveVideo = true; 106fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } else { 107fc9afba35492257e5e80a36b0765ff035908bb6dztenghui continue; 108fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 109fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 110fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (isVideo) { 111fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int width , height; 112fc9afba35492257e5e80a36b0765ff035908bb6dztenghui CHECK(format->findInt32("width", &width)); 113fc9afba35492257e5e80a36b0765ff035908bb6dztenghui CHECK(format->findInt32("height", &height)); 114fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bufferSize = width * height * 4; // Assuming it is maximally 4BPP 115fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 116fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 117fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int64_t duration; 118fc9afba35492257e5e80a36b0765ff035908bb6dztenghui CHECK(format->findInt64("durationUs", &duration)); 119fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 120fc9afba35492257e5e80a36b0765ff035908bb6dztenghui // Since we got the duration now, correct the start time. 121fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (enableTrim) { 122fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (trimStartTimeUs > duration) { 123fc9afba35492257e5e80a36b0765ff035908bb6dztenghui fprintf(stderr, "Warning: trimStartTimeUs > duration," 124fc9afba35492257e5e80a36b0765ff035908bb6dztenghui " reset to 0\n"); 125fc9afba35492257e5e80a36b0765ff035908bb6dztenghui trimStartTimeUs = 0; 126fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 127fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 128fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 129fc9afba35492257e5e80a36b0765ff035908bb6dztenghui ALOGV("selecting track %d", i); 130fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 131fc9afba35492257e5e80a36b0765ff035908bb6dztenghui err = extractor->selectTrack(i); 132fc9afba35492257e5e80a36b0765ff035908bb6dztenghui CHECK_EQ(err, (status_t)OK); 133fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 134fc9afba35492257e5e80a36b0765ff035908bb6dztenghui ssize_t newTrackIndex = muxer->addTrack(format); 135fc9afba35492257e5e80a36b0765ff035908bb6dztenghui CHECK_GE(newTrackIndex, 0); 136fc9afba35492257e5e80a36b0765ff035908bb6dztenghui trackIndexMap.add(i, newTrackIndex); 137fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 138fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 139fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int64_t muxerStartTimeUs = ALooper::GetNowUs(); 140fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 141fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bool sawInputEOS = false; 142fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 143fc9afba35492257e5e80a36b0765ff035908bb6dztenghui size_t trackIndex = -1; 144fc9afba35492257e5e80a36b0765ff035908bb6dztenghui sp<ABuffer> newBuffer = new ABuffer(bufferSize); 145fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 14611287471298193ff51ffb429686f5d63a84a621bztenghui muxer->setOrientationHint(rotationDegrees); 147fc9afba35492257e5e80a36b0765ff035908bb6dztenghui muxer->start(); 148fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 149fc9afba35492257e5e80a36b0765ff035908bb6dztenghui while (!sawInputEOS) { 150fc9afba35492257e5e80a36b0765ff035908bb6dztenghui status_t err = extractor->getSampleTrackIndex(&trackIndex); 151fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (err != OK) { 152fc9afba35492257e5e80a36b0765ff035908bb6dztenghui ALOGV("saw input eos, err %d", err); 153fc9afba35492257e5e80a36b0765ff035908bb6dztenghui sawInputEOS = true; 154fc9afba35492257e5e80a36b0765ff035908bb6dztenghui break; 155fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } else { 156fc9afba35492257e5e80a36b0765ff035908bb6dztenghui err = extractor->readSampleData(newBuffer); 157fc9afba35492257e5e80a36b0765ff035908bb6dztenghui CHECK_EQ(err, (status_t)OK); 158fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 159fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int64_t timeUs; 160fc9afba35492257e5e80a36b0765ff035908bb6dztenghui err = extractor->getSampleTime(&timeUs); 161fc9afba35492257e5e80a36b0765ff035908bb6dztenghui CHECK_EQ(err, (status_t)OK); 162fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 163fc9afba35492257e5e80a36b0765ff035908bb6dztenghui sp<MetaData> meta; 164fc9afba35492257e5e80a36b0765ff035908bb6dztenghui err = extractor->getSampleMeta(&meta); 165fc9afba35492257e5e80a36b0765ff035908bb6dztenghui CHECK_EQ(err, (status_t)OK); 166fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 167fc9afba35492257e5e80a36b0765ff035908bb6dztenghui uint32_t sampleFlags = 0; 168fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int32_t val; 169fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) { 170fc9afba35492257e5e80a36b0765ff035908bb6dztenghui // We only support BUFFER_FLAG_SYNCFRAME in the flag for now. 171fc9afba35492257e5e80a36b0765ff035908bb6dztenghui sampleFlags |= MediaCodec::BUFFER_FLAG_SYNCFRAME; 172fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 173fc9afba35492257e5e80a36b0765ff035908bb6dztenghui // We turn on trimming at the sync frame. 174fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (enableTrim && timeUs > trimStartTimeUs && 175fc9afba35492257e5e80a36b0765ff035908bb6dztenghui timeUs <= trimEndTimeUs) { 176fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (trimStarted == false) { 177fc9afba35492257e5e80a36b0765ff035908bb6dztenghui trimOffsetTimeUs = timeUs; 178fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 179fc9afba35492257e5e80a36b0765ff035908bb6dztenghui trimStarted = true; 180fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 181fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 182fc9afba35492257e5e80a36b0765ff035908bb6dztenghui // Trim can end at any non-sync frame. 183fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (enableTrim && timeUs > trimEndTimeUs) { 184fc9afba35492257e5e80a36b0765ff035908bb6dztenghui trimStarted = false; 185fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 186fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 187fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (!enableTrim || (enableTrim && trimStarted)) { 188fc9afba35492257e5e80a36b0765ff035908bb6dztenghui err = muxer->writeSampleData(newBuffer, 189fc9afba35492257e5e80a36b0765ff035908bb6dztenghui trackIndexMap.valueFor(trackIndex), 190fc9afba35492257e5e80a36b0765ff035908bb6dztenghui timeUs - trimOffsetTimeUs, sampleFlags); 191fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 192fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 193fc9afba35492257e5e80a36b0765ff035908bb6dztenghui extractor->advance(); 194fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 195fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 196fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 197fc9afba35492257e5e80a36b0765ff035908bb6dztenghui muxer->stop(); 198fc9afba35492257e5e80a36b0765ff035908bb6dztenghui newBuffer.clear(); 199fc9afba35492257e5e80a36b0765ff035908bb6dztenghui trackIndexMap.clear(); 200fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 201fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int64_t elapsedTimeUs = ALooper::GetNowUs() - muxerStartTimeUs; 202377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT fprintf(stderr, "SUCCESS: muxer generate the video in %" PRId64 " ms\n", 203fc9afba35492257e5e80a36b0765ff035908bb6dztenghui elapsedTimeUs / 1000); 204fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 205fc9afba35492257e5e80a36b0765ff035908bb6dztenghui return 0; 206fc9afba35492257e5e80a36b0765ff035908bb6dztenghui} 207fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 208fc9afba35492257e5e80a36b0765ff035908bb6dztenghuiint main(int argc, char **argv) { 209fc9afba35492257e5e80a36b0765ff035908bb6dztenghui const char *me = argv[0]; 210fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 211fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bool useAudio = false; 212fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bool useVideo = false; 213fc9afba35492257e5e80a36b0765ff035908bb6dztenghui char *outputFileName = NULL; 214fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int trimStartTimeMs = -1; 215fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int trimEndTimeMs = -1; 21611287471298193ff51ffb429686f5d63a84a621bztenghui int rotationDegrees = 0; 217fc9afba35492257e5e80a36b0765ff035908bb6dztenghui // When trimStartTimeMs and trimEndTimeMs seems valid, we turn this switch 218fc9afba35492257e5e80a36b0765ff035908bb6dztenghui // to true. 219fc9afba35492257e5e80a36b0765ff035908bb6dztenghui bool enableTrim = false; 220fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 221fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int res; 22211287471298193ff51ffb429686f5d63a84a621bztenghui while ((res = getopt(argc, argv, "h?avo:s:e:r:")) >= 0) { 223fc9afba35492257e5e80a36b0765ff035908bb6dztenghui switch (res) { 224fc9afba35492257e5e80a36b0765ff035908bb6dztenghui case 'a': 225fc9afba35492257e5e80a36b0765ff035908bb6dztenghui { 226fc9afba35492257e5e80a36b0765ff035908bb6dztenghui useAudio = true; 227fc9afba35492257e5e80a36b0765ff035908bb6dztenghui break; 228fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 229fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 230fc9afba35492257e5e80a36b0765ff035908bb6dztenghui case 'v': 231fc9afba35492257e5e80a36b0765ff035908bb6dztenghui { 232fc9afba35492257e5e80a36b0765ff035908bb6dztenghui useVideo = true; 233fc9afba35492257e5e80a36b0765ff035908bb6dztenghui break; 234fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 235fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 236fc9afba35492257e5e80a36b0765ff035908bb6dztenghui case 'o': 237fc9afba35492257e5e80a36b0765ff035908bb6dztenghui { 238fc9afba35492257e5e80a36b0765ff035908bb6dztenghui outputFileName = optarg; 239fc9afba35492257e5e80a36b0765ff035908bb6dztenghui break; 240fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 241fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 242fc9afba35492257e5e80a36b0765ff035908bb6dztenghui case 's': 243fc9afba35492257e5e80a36b0765ff035908bb6dztenghui { 244fc9afba35492257e5e80a36b0765ff035908bb6dztenghui trimStartTimeMs = atoi(optarg); 245fc9afba35492257e5e80a36b0765ff035908bb6dztenghui break; 246fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 247fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 248fc9afba35492257e5e80a36b0765ff035908bb6dztenghui case 'e': 249fc9afba35492257e5e80a36b0765ff035908bb6dztenghui { 250fc9afba35492257e5e80a36b0765ff035908bb6dztenghui trimEndTimeMs = atoi(optarg); 251fc9afba35492257e5e80a36b0765ff035908bb6dztenghui break; 252fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 253fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 25411287471298193ff51ffb429686f5d63a84a621bztenghui case 'r': 25511287471298193ff51ffb429686f5d63a84a621bztenghui { 25611287471298193ff51ffb429686f5d63a84a621bztenghui rotationDegrees = atoi(optarg); 25711287471298193ff51ffb429686f5d63a84a621bztenghui break; 25811287471298193ff51ffb429686f5d63a84a621bztenghui } 25911287471298193ff51ffb429686f5d63a84a621bztenghui 260fc9afba35492257e5e80a36b0765ff035908bb6dztenghui case '?': 261fc9afba35492257e5e80a36b0765ff035908bb6dztenghui case 'h': 262fc9afba35492257e5e80a36b0765ff035908bb6dztenghui default: 263fc9afba35492257e5e80a36b0765ff035908bb6dztenghui { 264fc9afba35492257e5e80a36b0765ff035908bb6dztenghui usage(me); 265fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 266fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 267fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 268fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 269fc9afba35492257e5e80a36b0765ff035908bb6dztenghui argc -= optind; 270fc9afba35492257e5e80a36b0765ff035908bb6dztenghui argv += optind; 271fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 272fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (argc != 1) { 273fc9afba35492257e5e80a36b0765ff035908bb6dztenghui usage(me); 274fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 275fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 276fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (trimStartTimeMs < 0 || trimEndTimeMs < 0) { 277fc9afba35492257e5e80a36b0765ff035908bb6dztenghui // If no input on either 's' or 'e', or they are obviously wrong input, 278fc9afba35492257e5e80a36b0765ff035908bb6dztenghui // then turn off trimming. 279fc9afba35492257e5e80a36b0765ff035908bb6dztenghui ALOGV("Trimming is disabled, copying the whole length video."); 280fc9afba35492257e5e80a36b0765ff035908bb6dztenghui enableTrim = false; 281fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } else if (trimStartTimeMs > trimEndTimeMs) { 282fc9afba35492257e5e80a36b0765ff035908bb6dztenghui fprintf(stderr, "ERROR: start time is bigger\n"); 283fc9afba35492257e5e80a36b0765ff035908bb6dztenghui return 1; 284fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } else { 285fc9afba35492257e5e80a36b0765ff035908bb6dztenghui enableTrim = true; 286fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 287fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 288fc9afba35492257e5e80a36b0765ff035908bb6dztenghui if (!useAudio && !useVideo) { 289fc9afba35492257e5e80a36b0765ff035908bb6dztenghui fprintf(stderr, "ERROR: Missing both -a and -v, no track to mux then.\n"); 290fc9afba35492257e5e80a36b0765ff035908bb6dztenghui return 1; 291fc9afba35492257e5e80a36b0765ff035908bb6dztenghui } 292fc9afba35492257e5e80a36b0765ff035908bb6dztenghui ProcessState::self()->startThreadPool(); 293fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 294fc9afba35492257e5e80a36b0765ff035908bb6dztenghui // Make sure setDataSource() works. 295fc9afba35492257e5e80a36b0765ff035908bb6dztenghui DataSource::RegisterDefaultSniffers(); 296fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 297fc9afba35492257e5e80a36b0765ff035908bb6dztenghui sp<ALooper> looper = new ALooper; 298fc9afba35492257e5e80a36b0765ff035908bb6dztenghui looper->start(); 299fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 300fc9afba35492257e5e80a36b0765ff035908bb6dztenghui int result = muxing(looper, argv[0], useAudio, useVideo, outputFileName, 30111287471298193ff51ffb429686f5d63a84a621bztenghui enableTrim, trimStartTimeMs, trimEndTimeMs, rotationDegrees); 302fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 303fc9afba35492257e5e80a36b0765ff035908bb6dztenghui looper->stop(); 304fc9afba35492257e5e80a36b0765ff035908bb6dztenghui 305fc9afba35492257e5e80a36b0765ff035908bb6dztenghui return result; 306fc9afba35492257e5e80a36b0765ff035908bb6dztenghui} 307