16df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui/* 26df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * Copyright (C) 2013 The Android Open Source Project 36df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * 46df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * Licensed under the Apache License, Version 2.0 (the "License"); 56df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * you may not use this file except in compliance with the License. 66df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * You may obtain a copy of the License at 76df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * 86df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * http://www.apache.org/licenses/LICENSE-2.0 96df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * 106df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * Unless required by applicable law or agreed to in writing, software 116df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * distributed under the License is distributed on an "AS IS" BASIS, 126df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * See the License for the specific language governing permissions and 146df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui * limitations under the License. 156df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui */ 166df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 176df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui//#define LOG_NDEBUG 0 186df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#define LOG_TAG "muxer" 19377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT#include <inttypes.h> 20c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen#include <sys/types.h> 21c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen#include <sys/stat.h> 22c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen#include <fcntl.h> 236df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <utils/Log.h> 246df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 256df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <binder/ProcessState.h> 261b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPService.h> 276df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/foundation/ABuffer.h> 286df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/foundation/ADebug.h> 296df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/foundation/ALooper.h> 306df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/foundation/AMessage.h> 316df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/foundation/AString.h> 326df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/DataSource.h> 336df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/MediaCodec.h> 346df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/MediaDefs.h> 356df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/MediaMuxer.h> 366df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/MetaData.h> 376df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/NuMediaExtractor.h> 386df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 396df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuistatic void usage(const char *me) { 406df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui fprintf(stderr, "usage: %s [-a] [-v] [-s <trim start time>]" 416df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui " [-e <trim end time>] [-o <output file>]" 426df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui " <input video file>\n", me); 436df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui fprintf(stderr, " -h help\n"); 446df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui fprintf(stderr, " -a use audio\n"); 456df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui fprintf(stderr, " -v use video\n"); 460ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar fprintf(stderr, " -w mux into WebM container (default is MP4)\n"); 476df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui fprintf(stderr, " -s Time in milli-seconds when the trim should start\n"); 486df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui fprintf(stderr, " -e Time in milli-seconds when the trim should end\n"); 496df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui fprintf(stderr, " -o output file name. Default is /sdcard/muxeroutput.mp4\n"); 506df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 516df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui exit(1); 526df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui} 536df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 546df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuiusing namespace android; 556df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 566df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuistatic int muxing( 576df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui const char *path, 586df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bool useAudio, 596df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bool useVideo, 606df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui const char *outputFileName, 616df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bool enableTrim, 626df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int trimStartTimeMs, 63e0fb528f8e3bbab04620c8534177168b358e837bztenghui int trimEndTimeMs, 640ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar int rotationDegrees, 650ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar MediaMuxer::OutputFormat container = MediaMuxer::OUTPUT_FORMAT_MPEG_4) { 666df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui sp<NuMediaExtractor> extractor = new NuMediaExtractor; 671b86fe063badb5f28c467ade39be0f4008688947Andreas Huber if (extractor->setDataSource(NULL /* httpService */, path) != OK) { 686df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui fprintf(stderr, "unable to instantiate extractor. %s\n", path); 696df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui return 1; 706df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 716df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 726df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (outputFileName == NULL) { 736df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui outputFileName = "/sdcard/muxeroutput.mp4"; 746df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 756df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 766df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui ALOGV("input file %s, output file %s", path, outputFileName); 776df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui ALOGV("useAudio %d, useVideo %d", useAudio, useVideo); 786df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 79c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen int fd = open(outputFileName, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); 80c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen 81c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen if (fd < 0) { 82c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen ALOGE("couldn't open file"); 83c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen return fd; 84c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen } 850ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar sp<MediaMuxer> muxer = new MediaMuxer(fd, container); 86c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen close(fd); 876df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 886df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui size_t trackCount = extractor->countTracks(); 896df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui // Map the extractor's track index to the muxer's track index. 906df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui KeyedVector<size_t, ssize_t> trackIndexMap; 916df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui size_t bufferSize = 1 * 1024 * 1024; // default buffer size is 1MB. 926df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 936df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bool haveAudio = false; 946df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bool haveVideo = false; 956df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 966df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int64_t trimStartTimeUs = trimStartTimeMs * 1000; 976df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int64_t trimEndTimeUs = trimEndTimeMs * 1000; 986df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bool trimStarted = false; 996df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int64_t trimOffsetTimeUs = 0; 1006df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1016df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui for (size_t i = 0; i < trackCount; ++i) { 1026df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui sp<AMessage> format; 1036df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui status_t err = extractor->getTrackFormat(i, &format); 1046df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui CHECK_EQ(err, (status_t)OK); 1056df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui ALOGV("extractor getTrackFormat: %s", format->debugString().c_str()); 1066df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1076df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui AString mime; 1086df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui CHECK(format->findString("mime", &mime)); 1096df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1106df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6); 1116df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bool isVideo = !strncasecmp(mime.c_str(), "video/", 6); 1126df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1136df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (useAudio && !haveAudio && isAudio) { 1146df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui haveAudio = true; 1156df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } else if (useVideo && !haveVideo && isVideo) { 1166df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui haveVideo = true; 1176df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } else { 1186df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui continue; 1196df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 1206df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1216df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (isVideo) { 1226df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int width , height; 1236df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui CHECK(format->findInt32("width", &width)); 1246df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui CHECK(format->findInt32("height", &height)); 1256df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bufferSize = width * height * 4; // Assuming it is maximally 4BPP 1266df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 1276df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1286df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int64_t duration; 1296df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui CHECK(format->findInt64("durationUs", &duration)); 1306df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1316df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui // Since we got the duration now, correct the start time. 1326df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (enableTrim) { 1336df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (trimStartTimeUs > duration) { 1346df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui fprintf(stderr, "Warning: trimStartTimeUs > duration," 1356df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui " reset to 0\n"); 1366df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui trimStartTimeUs = 0; 1376df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 1386df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 1396df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 14031de88566257d5546cf4eee9064d96926a4b0c24Lajos Molnar ALOGV("selecting track %zu", i); 1416df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1426df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui err = extractor->selectTrack(i); 1436df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui CHECK_EQ(err, (status_t)OK); 1446df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1456df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui ssize_t newTrackIndex = muxer->addTrack(format); 146a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih if (newTrackIndex < 0) { 14707a0ea7ce49c7de5efb0b2a432878d9a2a2c3cc7Marco Nelissen fprintf(stderr, "%s track (%zu) unsupported by muxer\n", 148a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih isAudio ? "audio" : "video", 149a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih i); 150a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih } else { 151a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih trackIndexMap.add(i, newTrackIndex); 152a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih } 1536df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 1546df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1556df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int64_t muxerStartTimeUs = ALooper::GetNowUs(); 1566df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1576df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bool sawInputEOS = false; 1586df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1596df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui size_t trackIndex = -1; 1606df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui sp<ABuffer> newBuffer = new ABuffer(bufferSize); 1616df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 162e0fb528f8e3bbab04620c8534177168b358e837bztenghui muxer->setOrientationHint(rotationDegrees); 1636df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui muxer->start(); 1646df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1656df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui while (!sawInputEOS) { 1666df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui status_t err = extractor->getSampleTrackIndex(&trackIndex); 1676df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (err != OK) { 1686df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui ALOGV("saw input eos, err %d", err); 1696df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui sawInputEOS = true; 1706df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui break; 171a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih } else if (trackIndexMap.indexOfKey(trackIndex) < 0) { 172a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih // ALOGV("skipping input from unsupported track %zu", trackIndex); 173a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih extractor->advance(); 174a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih continue; 1756df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } else { 176a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih // ALOGV("reading sample from track index %zu\n", trackIndex); 1776df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui err = extractor->readSampleData(newBuffer); 1786df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui CHECK_EQ(err, (status_t)OK); 1796df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1806df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int64_t timeUs; 1816df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui err = extractor->getSampleTime(&timeUs); 1826df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui CHECK_EQ(err, (status_t)OK); 1836df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1846df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui sp<MetaData> meta; 1856df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui err = extractor->getSampleMeta(&meta); 1866df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui CHECK_EQ(err, (status_t)OK); 1876df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1886df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui uint32_t sampleFlags = 0; 1896df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int32_t val; 1906df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) { 1916df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui // We only support BUFFER_FLAG_SYNCFRAME in the flag for now. 1926df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui sampleFlags |= MediaCodec::BUFFER_FLAG_SYNCFRAME; 1936df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 1946df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui // We turn on trimming at the sync frame. 1956df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (enableTrim && timeUs > trimStartTimeUs && 1966df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui timeUs <= trimEndTimeUs) { 1976df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (trimStarted == false) { 1986df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui trimOffsetTimeUs = timeUs; 1996df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2006df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui trimStarted = true; 2016df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2026df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2036df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui // Trim can end at any non-sync frame. 2046df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (enableTrim && timeUs > trimEndTimeUs) { 2056df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui trimStarted = false; 2066df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2076df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2086df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (!enableTrim || (enableTrim && trimStarted)) { 2096df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui err = muxer->writeSampleData(newBuffer, 2106df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui trackIndexMap.valueFor(trackIndex), 2116df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui timeUs - trimOffsetTimeUs, sampleFlags); 2126df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2136df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2146df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui extractor->advance(); 2156df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2166df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2176df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2186df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui muxer->stop(); 2196df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui newBuffer.clear(); 2206df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui trackIndexMap.clear(); 2216df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2226df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int64_t elapsedTimeUs = ALooper::GetNowUs() - muxerStartTimeUs; 223377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT fprintf(stderr, "SUCCESS: muxer generate the video in %" PRId64 " ms\n", 2246df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui elapsedTimeUs / 1000); 2256df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2266df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui return 0; 2276df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui} 2286df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2296df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuiint main(int argc, char **argv) { 2306df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui const char *me = argv[0]; 2316df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2326df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bool useAudio = false; 2336df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bool useVideo = false; 2346df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui char *outputFileName = NULL; 2356df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int trimStartTimeMs = -1; 2366df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int trimEndTimeMs = -1; 237e0fb528f8e3bbab04620c8534177168b358e837bztenghui int rotationDegrees = 0; 2386df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui // When trimStartTimeMs and trimEndTimeMs seems valid, we turn this switch 2396df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui // to true. 2406df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui bool enableTrim = false; 2410ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar MediaMuxer::OutputFormat container = MediaMuxer::OUTPUT_FORMAT_MPEG_4; 2426df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2436df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui int res; 2440ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar while ((res = getopt(argc, argv, "h?avo:s:e:r:w")) >= 0) { 2456df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui switch (res) { 2466df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui case 'a': 2476df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui { 2486df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui useAudio = true; 2496df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui break; 2506df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2516df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2526df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui case 'v': 2536df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui { 2546df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui useVideo = true; 2556df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui break; 2566df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2576df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2580ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar case 'w': 2590ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar { 2600ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar container = MediaMuxer::OUTPUT_FORMAT_WEBM; 2610ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar break; 2620ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar } 2630ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar 2646df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui case 'o': 2656df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui { 2666df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui outputFileName = optarg; 2676df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui break; 2686df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2696df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2706df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui case 's': 2716df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui { 2726df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui trimStartTimeMs = atoi(optarg); 2736df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui break; 2746df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2756df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2766df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui case 'e': 2776df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui { 2786df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui trimEndTimeMs = atoi(optarg); 2796df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui break; 2806df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2816df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 282e0fb528f8e3bbab04620c8534177168b358e837bztenghui case 'r': 283e0fb528f8e3bbab04620c8534177168b358e837bztenghui { 284e0fb528f8e3bbab04620c8534177168b358e837bztenghui rotationDegrees = atoi(optarg); 285e0fb528f8e3bbab04620c8534177168b358e837bztenghui break; 286e0fb528f8e3bbab04620c8534177168b358e837bztenghui } 287e0fb528f8e3bbab04620c8534177168b358e837bztenghui 2886df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui case '?': 2896df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui case 'h': 2906df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui default: 2916df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui { 2926df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui usage(me); 2936df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2946df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2956df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 2966df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 2976df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui argc -= optind; 2986df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui argv += optind; 2996df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 3006df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (argc != 1) { 3016df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui usage(me); 3026df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 3036df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 3046df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (trimStartTimeMs < 0 || trimEndTimeMs < 0) { 3056df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui // If no input on either 's' or 'e', or they are obviously wrong input, 3066df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui // then turn off trimming. 3076df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui ALOGV("Trimming is disabled, copying the whole length video."); 3086df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui enableTrim = false; 3096df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } else if (trimStartTimeMs > trimEndTimeMs) { 3106df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui fprintf(stderr, "ERROR: start time is bigger\n"); 3116df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui return 1; 3126df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } else { 3136df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui enableTrim = true; 3146df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 3156df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 3166df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui if (!useAudio && !useVideo) { 3176df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui fprintf(stderr, "ERROR: Missing both -a and -v, no track to mux then.\n"); 3186df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui return 1; 3196df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui } 3206df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui ProcessState::self()->startThreadPool(); 3216df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 3226df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui // Make sure setDataSource() works. 3236df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui DataSource::RegisterDefaultSniffers(); 3246df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 3256df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui sp<ALooper> looper = new ALooper; 3266df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui looper->start(); 3276df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 32831de88566257d5546cf4eee9064d96926a4b0c24Lajos Molnar int result = muxing(argv[0], useAudio, useVideo, outputFileName, 3290ce6e969ccce7b5826630484c5574252c4ca6acdLajos Molnar enableTrim, trimStartTimeMs, trimEndTimeMs, rotationDegrees, container); 3306df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 3316df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui looper->stop(); 3326df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui 3336df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui return result; 3346df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui} 335