muxer.cpp revision 1b86fe063badb5f28c467ade39be0f4008688947
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"
196df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <utils/Log.h>
206df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
216df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <binder/ProcessState.h>
221b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPService.h>
236df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/foundation/ABuffer.h>
246df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/foundation/ADebug.h>
256df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/foundation/ALooper.h>
266df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/foundation/AMessage.h>
276df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/foundation/AString.h>
286df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/DataSource.h>
296df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/MediaCodec.h>
306df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/MediaDefs.h>
316df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/MediaMuxer.h>
326df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/MetaData.h>
336df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui#include <media/stagefright/NuMediaExtractor.h>
346df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
356df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuistatic void usage(const char *me) {
366df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    fprintf(stderr, "usage: %s [-a] [-v] [-s <trim start time>]"
376df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                    " [-e <trim end time>] [-o <output file>]"
386df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                    " <input video file>\n", me);
396df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    fprintf(stderr, "       -h help\n");
406df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    fprintf(stderr, "       -a use audio\n");
416df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    fprintf(stderr, "       -v use video\n");
426df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    fprintf(stderr, "       -s Time in milli-seconds when the trim should start\n");
436df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    fprintf(stderr, "       -e Time in milli-seconds when the trim should end\n");
446df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    fprintf(stderr, "       -o output file name. Default is /sdcard/muxeroutput.mp4\n");
456df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
466df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    exit(1);
476df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui}
486df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
496df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuiusing namespace android;
506df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
516df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuistatic int muxing(
526df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        const android::sp<android::ALooper> &looper,
536df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        const char *path,
546df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        bool useAudio,
556df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        bool useVideo,
566df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        const char *outputFileName,
576df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        bool enableTrim,
586df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        int trimStartTimeMs,
59e0fb528f8e3bbab04620c8534177168b358e837bztenghui        int trimEndTimeMs,
60e0fb528f8e3bbab04620c8534177168b358e837bztenghui        int rotationDegrees) {
616df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    sp<NuMediaExtractor> extractor = new NuMediaExtractor;
621b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
636df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        fprintf(stderr, "unable to instantiate extractor. %s\n", path);
646df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        return 1;
656df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
666df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
676df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    if (outputFileName == NULL) {
686df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        outputFileName = "/sdcard/muxeroutput.mp4";
696df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
706df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
716df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    ALOGV("input file %s, output file %s", path, outputFileName);
726df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    ALOGV("useAudio %d, useVideo %d", useAudio, useVideo);
736df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
743db62dfc5102247d415df4667bd9609e669fc022ztenghui    sp<MediaMuxer> muxer = new MediaMuxer(outputFileName,
753db62dfc5102247d415df4667bd9609e669fc022ztenghui                                          MediaMuxer::OUTPUT_FORMAT_MPEG_4);
766df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
776df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    size_t trackCount = extractor->countTracks();
786df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    // Map the extractor's track index to the muxer's track index.
796df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    KeyedVector<size_t, ssize_t> trackIndexMap;
806df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    size_t bufferSize = 1 * 1024 * 1024;  // default buffer size is 1MB.
816df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
826df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool haveAudio = false;
836df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool haveVideo = false;
846df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
856df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int64_t trimStartTimeUs = trimStartTimeMs * 1000;
866df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int64_t trimEndTimeUs = trimEndTimeMs * 1000;
876df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool trimStarted = false;
886df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int64_t trimOffsetTimeUs = 0;
896df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
906df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    for (size_t i = 0; i < trackCount; ++i) {
916df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        sp<AMessage> format;
926df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        status_t err = extractor->getTrackFormat(i, &format);
936df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        CHECK_EQ(err, (status_t)OK);
946df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        ALOGV("extractor getTrackFormat: %s", format->debugString().c_str());
956df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
966df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        AString mime;
976df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        CHECK(format->findString("mime", &mime));
986df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
996df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6);
1006df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        bool isVideo = !strncasecmp(mime.c_str(), "video/", 6);
1016df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1026df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        if (useAudio && !haveAudio && isAudio) {
1036df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            haveAudio = true;
1046df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        } else if (useVideo && !haveVideo && isVideo) {
1056df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            haveVideo = true;
1066df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        } else {
1076df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            continue;
1086df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        }
1096df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1106df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        if (isVideo) {
1116df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            int width , height;
1126df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            CHECK(format->findInt32("width", &width));
1136df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            CHECK(format->findInt32("height", &height));
1146df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            bufferSize = width * height * 4;  // Assuming it is maximally 4BPP
1156df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        }
1166df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1176df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        int64_t duration;
1186df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        CHECK(format->findInt64("durationUs", &duration));
1196df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1206df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        // Since we got the duration now, correct the start time.
1216df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        if (enableTrim) {
1226df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            if (trimStartTimeUs > duration) {
1236df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                fprintf(stderr, "Warning: trimStartTimeUs > duration,"
1246df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                                " reset to 0\n");
1256df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                trimStartTimeUs = 0;
1266df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
1276df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        }
1286df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1296df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        ALOGV("selecting track %d", i);
1306df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1316df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        err = extractor->selectTrack(i);
1326df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        CHECK_EQ(err, (status_t)OK);
1336df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1346df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        ssize_t newTrackIndex = muxer->addTrack(format);
1356df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        CHECK_GE(newTrackIndex, 0);
1366df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        trackIndexMap.add(i, newTrackIndex);
1376df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
1386df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1396df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int64_t muxerStartTimeUs = ALooper::GetNowUs();
1406df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1416df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool sawInputEOS = false;
1426df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1436df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    size_t trackIndex = -1;
1446df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    sp<ABuffer> newBuffer = new ABuffer(bufferSize);
1456df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
146e0fb528f8e3bbab04620c8534177168b358e837bztenghui    muxer->setOrientationHint(rotationDegrees);
1476df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    muxer->start();
1486df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1496df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    while (!sawInputEOS) {
1506df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        status_t err = extractor->getSampleTrackIndex(&trackIndex);
1516df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        if (err != OK) {
1526df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            ALOGV("saw input eos, err %d", err);
1536df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            sawInputEOS = true;
1546df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            break;
1556df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        } else {
1566df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            err = extractor->readSampleData(newBuffer);
1576df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            CHECK_EQ(err, (status_t)OK);
1586df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1596df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            int64_t timeUs;
1606df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            err = extractor->getSampleTime(&timeUs);
1616df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            CHECK_EQ(err, (status_t)OK);
1626df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1636df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            sp<MetaData> meta;
1646df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            err = extractor->getSampleMeta(&meta);
1656df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            CHECK_EQ(err, (status_t)OK);
1666df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1676df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            uint32_t sampleFlags = 0;
1686df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            int32_t val;
1696df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) {
1706df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                // We only support BUFFER_FLAG_SYNCFRAME in the flag for now.
1716df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                sampleFlags |= MediaCodec::BUFFER_FLAG_SYNCFRAME;
1726df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1736df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                // We turn on trimming at the sync frame.
1746df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                if (enableTrim && timeUs > trimStartTimeUs &&
1756df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                    timeUs <= trimEndTimeUs) {
1766df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                    if (trimStarted == false) {
1776df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                        trimOffsetTimeUs = timeUs;
1786df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                    }
1796df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                    trimStarted = true;
1806df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                }
1816df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
1826df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            // Trim can end at any non-sync frame.
1836df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            if (enableTrim && timeUs > trimEndTimeUs) {
1846df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                trimStarted = false;
1856df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
1866df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1876df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            if (!enableTrim || (enableTrim && trimStarted)) {
1886df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                err = muxer->writeSampleData(newBuffer,
1896df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                                             trackIndexMap.valueFor(trackIndex),
1906df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                                             timeUs - trimOffsetTimeUs, sampleFlags);
1916df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
1926df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1936df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            extractor->advance();
1946df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        }
1956df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
1966df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
1976df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    muxer->stop();
1986df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    newBuffer.clear();
1996df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    trackIndexMap.clear();
2006df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2016df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int64_t elapsedTimeUs = ALooper::GetNowUs() - muxerStartTimeUs;
2026df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    fprintf(stderr, "SUCCESS: muxer generate the video in %lld ms\n",
2036df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            elapsedTimeUs / 1000);
2046df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2056df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    return 0;
2066df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui}
2076df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2086df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghuiint main(int argc, char **argv) {
2096df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    const char *me = argv[0];
2106df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2116df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool useAudio = false;
2126df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool useVideo = false;
2136df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    char *outputFileName = NULL;
2146df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int trimStartTimeMs = -1;
2156df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int trimEndTimeMs = -1;
216e0fb528f8e3bbab04620c8534177168b358e837bztenghui    int rotationDegrees = 0;
2176df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    // When trimStartTimeMs and trimEndTimeMs seems valid, we turn this switch
2186df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    // to true.
2196df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    bool enableTrim = false;
2206df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2216df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int res;
222e0fb528f8e3bbab04620c8534177168b358e837bztenghui    while ((res = getopt(argc, argv, "h?avo:s:e:r:")) >= 0) {
2236df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        switch (res) {
2246df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case 'a':
2256df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            {
2266df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                useAudio = true;
2276df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                break;
2286df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2296df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2306df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case 'v':
2316df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            {
2326df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                useVideo = true;
2336df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                break;
2346df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2356df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2366df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case 'o':
2376df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            {
2386df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                outputFileName = optarg;
2396df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                break;
2406df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2416df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2426df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case 's':
2436df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            {
2446df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                trimStartTimeMs = atoi(optarg);
2456df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                break;
2466df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2476df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2486df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case 'e':
2496df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            {
2506df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                trimEndTimeMs = atoi(optarg);
2516df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                break;
2526df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2536df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
254e0fb528f8e3bbab04620c8534177168b358e837bztenghui            case 'r':
255e0fb528f8e3bbab04620c8534177168b358e837bztenghui            {
256e0fb528f8e3bbab04620c8534177168b358e837bztenghui                rotationDegrees = atoi(optarg);
257e0fb528f8e3bbab04620c8534177168b358e837bztenghui                break;
258e0fb528f8e3bbab04620c8534177168b358e837bztenghui            }
259e0fb528f8e3bbab04620c8534177168b358e837bztenghui
2606df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case '?':
2616df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            case 'h':
2626df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            default:
2636df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            {
2646df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui                usage(me);
2656df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui            }
2666df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        }
2676df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
2686df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2696df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    argc -= optind;
2706df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    argv += optind;
2716df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2726df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    if (argc != 1) {
2736df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        usage(me);
2746df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
2756df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2766df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    if (trimStartTimeMs < 0 || trimEndTimeMs < 0) {
2776df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        // If no input on either 's' or 'e', or they are obviously wrong input,
2786df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        // then turn off trimming.
2796df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        ALOGV("Trimming is disabled, copying the whole length video.");
2806df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        enableTrim = false;
2816df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    } else if (trimStartTimeMs > trimEndTimeMs) {
2826df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        fprintf(stderr, "ERROR: start time is bigger\n");
2836df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        return 1;
2846df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    } else {
2856df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        enableTrim = true;
2866df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
2876df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2886df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    if (!useAudio && !useVideo) {
2896df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        fprintf(stderr, "ERROR: Missing both -a and -v, no track to mux then.\n");
2906df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui        return 1;
2916df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    }
2926df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    ProcessState::self()->startThreadPool();
2936df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2946df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    // Make sure setDataSource() works.
2956df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    DataSource::RegisterDefaultSniffers();
2966df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
2976df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    sp<ALooper> looper = new ALooper;
2986df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    looper->start();
2996df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
3006df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    int result = muxing(looper, argv[0], useAudio, useVideo, outputFileName,
301e0fb528f8e3bbab04620c8534177168b358e837bztenghui                        enableTrim, trimStartTimeMs, trimEndTimeMs, rotationDegrees);
3026df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
3036df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    looper->stop();
3046df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui
3056df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui    return result;
3066df48bfe8cccdfec58f5f94be3cf3a2c64697e56ztenghui}
307