muxer.cpp revision 07a0ea7ce49c7de5efb0b2a432878d9a2a2c3cc7
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");
466df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    fprintf(stderr, "       -s Time in milli-seconds when the trim should start\n");
476df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    fprintf(stderr, "       -e Time in milli-seconds when the trim should end\n");
486df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    fprintf(stderr, "       -o output file name. Default is /sdcard/muxeroutput.mp4\n");
496df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
506df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    exit(1);
516df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui}
526df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
536df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuiusing namespace android;
546df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
556df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuistatic int muxing(
566df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        const char *path,
576df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        bool useAudio,
586df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        bool useVideo,
596df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        const char *outputFileName,
606df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        bool enableTrim,
616df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        int trimStartTimeMs,
62e0fb528f8e3bbab04620c8534177168b358e837bztenghui        int trimEndTimeMs,
63e0fb528f8e3bbab04620c8534177168b358e837bztenghui        int rotationDegrees) {
646df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    sp<NuMediaExtractor> extractor = new NuMediaExtractor;
651b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
666df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        fprintf(stderr, "unable to instantiate extractor. %s\n", path);
676df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        return 1;
686df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
696df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
706df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    if (outputFileName == NULL) {
716df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        outputFileName = "/sdcard/muxeroutput.mp4";
726df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
736df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
746df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    ALOGV("input file %s, output file %s", path, outputFileName);
756df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    ALOGV("useAudio %d, useVideo %d", useAudio, useVideo);
766df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
77c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen    int fd = open(outputFileName, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
78c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen
79c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen    if (fd < 0) {
80c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen        ALOGE("couldn't open file");
81c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen        return fd;
82c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen    }
83c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen    sp<MediaMuxer> muxer = new MediaMuxer(fd,
843db62dfc5102247d415df4667bd9609e669fc022ztenghui                                          MediaMuxer::OUTPUT_FORMAT_MPEG_4);
85c6ac859f5a82ea8642bc6351a45508a15f224f32Marco Nelissen    close(fd);
866df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
876df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    size_t trackCount = extractor->countTracks();
886df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    // Map the extractor's track index to the muxer's track index.
896df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    KeyedVector<size_t, ssize_t> trackIndexMap;
906df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    size_t bufferSize = 1 * 1024 * 1024;  // default buffer size is 1MB.
916df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
926df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool haveAudio = false;
936df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool haveVideo = false;
946df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
956df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int64_t trimStartTimeUs = trimStartTimeMs * 1000;
966df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int64_t trimEndTimeUs = trimEndTimeMs * 1000;
976df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool trimStarted = false;
986df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int64_t trimOffsetTimeUs = 0;
996df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1006df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    for (size_t i = 0; i < trackCount; ++i) {
1016df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        sp<AMessage> format;
1026df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        status_t err = extractor->getTrackFormat(i, &format);
1036df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        CHECK_EQ(err, (status_t)OK);
1046df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        ALOGV("extractor getTrackFormat: %s", format->debugString().c_str());
1056df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1066df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        AString mime;
1076df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        CHECK(format->findString("mime", &mime));
1086df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1096df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6);
1106df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        bool isVideo = !strncasecmp(mime.c_str(), "video/", 6);
1116df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1126df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        if (useAudio && !haveAudio && isAudio) {
1136df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            haveAudio = true;
1146df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        } else if (useVideo && !haveVideo && isVideo) {
1156df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            haveVideo = true;
1166df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        } else {
1176df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            continue;
1186df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        }
1196df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1206df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        if (isVideo) {
1216df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            int width , height;
1226df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            CHECK(format->findInt32("width", &width));
1236df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            CHECK(format->findInt32("height", &height));
1246df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            bufferSize = width * height * 4;  // Assuming it is maximally 4BPP
1256df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        }
1266df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1276df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        int64_t duration;
1286df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        CHECK(format->findInt64("durationUs", &duration));
1296df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1306df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        // Since we got the duration now, correct the start time.
1316df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        if (enableTrim) {
1326df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            if (trimStartTimeUs > duration) {
1336df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                fprintf(stderr, "Warning: trimStartTimeUs > duration,"
1346df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                                " reset to 0\n");
1356df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                trimStartTimeUs = 0;
1366df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
1376df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        }
1386df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
13931de88566257d5546cf4eee9064d96926a4b0c24Lajos Molnar        ALOGV("selecting track %zu", i);
1406df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1416df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        err = extractor->selectTrack(i);
1426df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        CHECK_EQ(err, (status_t)OK);
1436df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1446df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        ssize_t newTrackIndex = muxer->addTrack(format);
145a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih        if (newTrackIndex < 0) {
14607a0ea7ce49c7de5efb0b2a432878d9a2a2c3cc7Marco Nelissen            fprintf(stderr, "%s track (%zu) unsupported by muxer\n",
147a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih                    isAudio ? "audio" : "video",
148a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih                    i);
149a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih        } else {
150a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih            trackIndexMap.add(i, newTrackIndex);
151a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih        }
1526df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
1536df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1546df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int64_t muxerStartTimeUs = ALooper::GetNowUs();
1556df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1566df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool sawInputEOS = false;
1576df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1586df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    size_t trackIndex = -1;
1596df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    sp<ABuffer> newBuffer = new ABuffer(bufferSize);
1606df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
161e0fb528f8e3bbab04620c8534177168b358e837bztenghui    muxer->setOrientationHint(rotationDegrees);
1626df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    muxer->start();
1636df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1646df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    while (!sawInputEOS) {
1656df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        status_t err = extractor->getSampleTrackIndex(&trackIndex);
1666df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        if (err != OK) {
1676df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            ALOGV("saw input eos, err %d", err);
1686df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            sawInputEOS = true;
1696df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            break;
170a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih        } else if (trackIndexMap.indexOfKey(trackIndex) < 0) {
171a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih            // ALOGV("skipping input from unsupported track %zu", trackIndex);
172a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih            extractor->advance();
173a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih            continue;
1746df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        } else {
175a0cf6c4d7d13c73feef5b88760b52b18289b0db2Robert Shih            // ALOGV("reading sample from track index %zu\n", trackIndex);
1766df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            err = extractor->readSampleData(newBuffer);
1776df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            CHECK_EQ(err, (status_t)OK);
1786df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1796df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            int64_t timeUs;
1806df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            err = extractor->getSampleTime(&timeUs);
1816df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            CHECK_EQ(err, (status_t)OK);
1826df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1836df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            sp<MetaData> meta;
1846df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            err = extractor->getSampleMeta(&meta);
1856df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            CHECK_EQ(err, (status_t)OK);
1866df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1876df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            uint32_t sampleFlags = 0;
1886df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            int32_t val;
1896df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) {
1906df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                // We only support BUFFER_FLAG_SYNCFRAME in the flag for now.
1916df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                sampleFlags |= MediaCodec::BUFFER_FLAG_SYNCFRAME;
1926df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1936df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                // We turn on trimming at the sync frame.
1946df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                if (enableTrim && timeUs > trimStartTimeUs &&
1956df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                    timeUs <= trimEndTimeUs) {
1966df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                    if (trimStarted == false) {
1976df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                        trimOffsetTimeUs = timeUs;
1986df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                    }
1996df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                    trimStarted = true;
2006df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                }
2016df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2026df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            // Trim can end at any non-sync frame.
2036df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            if (enableTrim && timeUs > trimEndTimeUs) {
2046df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                trimStarted = false;
2056df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2066df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2076df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            if (!enableTrim || (enableTrim && trimStarted)) {
2086df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                err = muxer->writeSampleData(newBuffer,
2096df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                                             trackIndexMap.valueFor(trackIndex),
2106df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                                             timeUs - trimOffsetTimeUs, sampleFlags);
2116df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2126df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2136df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            extractor->advance();
2146df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        }
2156df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
2166df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2176df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    muxer->stop();
2186df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    newBuffer.clear();
2196df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    trackIndexMap.clear();
2206df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2216df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int64_t elapsedTimeUs = ALooper::GetNowUs() - muxerStartTimeUs;
222377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT    fprintf(stderr, "SUCCESS: muxer generate the video in %" PRId64 " ms\n",
2236df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            elapsedTimeUs / 1000);
2246df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2256df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    return 0;
2266df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui}
2276df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2286df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuiint main(int argc, char **argv) {
2296df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    const char *me = argv[0];
2306df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2316df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool useAudio = false;
2326df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool useVideo = false;
2336df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    char *outputFileName = NULL;
2346df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int trimStartTimeMs = -1;
2356df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int trimEndTimeMs = -1;
236e0fb528f8e3bbab04620c8534177168b358e837bztenghui    int rotationDegrees = 0;
2376df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    // When trimStartTimeMs and trimEndTimeMs seems valid, we turn this switch
2386df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    // to true.
2396df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool enableTrim = false;
2406df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2416df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int res;
242e0fb528f8e3bbab04620c8534177168b358e837bztenghui    while ((res = getopt(argc, argv, "h?avo:s:e:r:")) >= 0) {
2436df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        switch (res) {
2446df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case 'a':
2456df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            {
2466df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                useAudio = true;
2476df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                break;
2486df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2496df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2506df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case 'v':
2516df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            {
2526df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                useVideo = true;
2536df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                break;
2546df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2556df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2566df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case 'o':
2576df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            {
2586df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                outputFileName = optarg;
2596df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                break;
2606df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2616df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2626df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case 's':
2636df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            {
2646df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                trimStartTimeMs = atoi(optarg);
2656df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                break;
2666df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2676df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2686df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case 'e':
2696df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            {
2706df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                trimEndTimeMs = atoi(optarg);
2716df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                break;
2726df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2736df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
274e0fb528f8e3bbab04620c8534177168b358e837bztenghui            case 'r':
275e0fb528f8e3bbab04620c8534177168b358e837bztenghui            {
276e0fb528f8e3bbab04620c8534177168b358e837bztenghui                rotationDegrees = atoi(optarg);
277e0fb528f8e3bbab04620c8534177168b358e837bztenghui                break;
278e0fb528f8e3bbab04620c8534177168b358e837bztenghui            }
279e0fb528f8e3bbab04620c8534177168b358e837bztenghui
2806df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case '?':
2816df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case 'h':
2826df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            default:
2836df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            {
2846df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                usage(me);
2856df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2866df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        }
2876df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
2886df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2896df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    argc -= optind;
2906df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    argv += optind;
2916df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2926df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    if (argc != 1) {
2936df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        usage(me);
2946df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
2956df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2966df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    if (trimStartTimeMs < 0 || trimEndTimeMs < 0) {
2976df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        // If no input on either 's' or 'e', or they are obviously wrong input,
2986df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        // then turn off trimming.
2996df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        ALOGV("Trimming is disabled, copying the whole length video.");
3006df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        enableTrim = false;
3016df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    } else if (trimStartTimeMs > trimEndTimeMs) {
3026df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        fprintf(stderr, "ERROR: start time is bigger\n");
3036df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        return 1;
3046df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    } else {
3056df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        enableTrim = true;
3066df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
3076df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
3086df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    if (!useAudio && !useVideo) {
3096df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        fprintf(stderr, "ERROR: Missing both -a and -v, no track to mux then.\n");
3106df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        return 1;
3116df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
3126df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    ProcessState::self()->startThreadPool();
3136df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
3146df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    // Make sure setDataSource() works.
3156df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    DataSource::RegisterDefaultSniffers();
3166df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
3176df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    sp<ALooper> looper = new ALooper;
3186df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    looper->start();
3196df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
32031de88566257d5546cf4eee9064d96926a4b0c24Lajos Molnar    int result = muxing(argv[0], useAudio, useVideo, outputFileName,
321e0fb528f8e3bbab04620c8534177168b358e837bztenghui                        enableTrim, trimStartTimeMs, trimEndTimeMs, rotationDegrees);
3226df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
3236df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    looper->stop();
3246df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
3256df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    return result;
3266df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui}
327