Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/204.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用MediaCodec、Media Extractor和Media Muxer在Android上进行视频剪辑_Android_Video_Android Mediacodec_Mediamuxer - Fatal编程技术网

使用MediaCodec、Media Extractor和Media Muxer在Android上进行视频剪辑

使用MediaCodec、Media Extractor和Media Muxer在Android上进行视频剪辑,android,video,android-mediacodec,mediamuxer,Android,Video,Android Mediacodec,Mediamuxer,在我的Android应用程序中,我需要一个解决方案,当用户可以从内部存储中修剪视频时。我试图在不使用任何第三方库的情况下实现这一点。我引用的是谷歌的Gallery应用程序源代码。但我得到了以下错误: 视频曲目的时间戳66733

在我的Android应用程序中,我需要一个解决方案,当用户可以从内部存储中修剪视频时。我试图在不使用任何第三方库的情况下实现这一点。我引用的是谷歌的Gallery应用程序源代码。但我得到了以下错误:

视频曲目的时间戳66733<时间戳133467

关于时间戳的问题很少有这样的问题,但我真的没有弄明白,因为我对使用MediaCodec、MediaMuxer等还不熟悉。如果有任何问题可以帮助解决,那就太好了

这是我的密码:

 // Set up MediaExtractor to read from the source.
    MediaExtractor extractor = new MediaExtractor();
    extractor.setDataSource(srcPath);
    int trackCount = extractor.getTrackCount();
    System.out.println("tracl" + trackCount);
    // Set up MediaMuxer for the destination.
    MediaMuxer muxer;
    muxer = new MediaMuxer(dstPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);



    // Set up the tracks and retrieve the max buffer size for selected
    // tracks.
    HashMap<Integer, Integer> indexMap = new HashMap<>(trackCount);
    int bufferSize = -1;
    for (int i = 0; i < trackCount; i++) {
        MediaFormat format = extractor.getTrackFormat(i);


        String mime = format.getString(MediaFormat.KEY_MIME);
        boolean selectCurrentTrack = false;
        if (mime.startsWith("audio/") && useAudio) {
            selectCurrentTrack = true;
        } else if (mime.startsWith("video/") && useVideo) {
            selectCurrentTrack = true;
        }
        if (selectCurrentTrack) {
            extractor.selectTrack(i);
            int dstIndex = muxer.addTrack(format);
            System.out.println(format);
            System.out.println("dstIndex" + dstIndex);

            indexMap.put(i, dstIndex);
            if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
                int newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
                bufferSize = newSize > bufferSize ? newSize : bufferSize;
            }
        }
    }

    System.out.println(indexMap);

    if (bufferSize < 0) {
        bufferSize = DEFAULT_BUFFER_SIZE;
    }
    // Set up the orientation and starting time for extractor.
    MediaMetadataRetriever retrieverSrc = new MediaMetadataRetriever();
    retrieverSrc.setDataSource(srcPath);
    String degreesString = retrieverSrc.extractMetadata(
            MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
    if (degreesString != null) {
        int degrees = Integer.parseInt(degreesString);
        if (degrees >= 0) {
            muxer.setOrientationHint(degrees);
        }
    }
    if (startMs > 0) {
        extractor.seekTo(startMs * 1000, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
    }


  //  System.out.println(extractor.);
    // Copy the samples from MediaExtractor to MediaMuxer. We will loop
    // for copying each sample and stop when we get to the end of the source
    // file or exceed the end time of the trimming.
    int offset = 0;
    int trackIndex = -1;
    ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize);
    MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();


    try {
        muxer.start();
        while (true) {

            System.out.println("copying");
            bufferInfo.offset = offset;


            bufferInfo.size = extractor.readSampleData(dstBuf, offset);



            if (bufferInfo.size < 0 ) {
               // InstabugSDKLogger.d(TAG, "Saw input EOS.");
                System.out.println("Saw input EOS.");
                bufferInfo.size = 0;
                break;
            } else {

                /**
                 * The presentation timestamp in microseconds for the buffer.
                 * This is derived from the presentation timestamp passed in
                 * with the corresponding input buffer.  This should be ignored for
                 * a 0-sized buffer.
                 */

                /**
                 * Returns the current sample's presentation time in microseconds.
                 * or -1 if no more samples are available.
                 */
                bufferInfo.presentationTimeUs = extractor.getSampleTime();

                //1 sec = 1000000 micco sec


                if (endMs > 0 && bufferInfo.presentationTimeUs > (endMs * 1000)) {


                    break;
                } else {
                    bufferInfo.flags = extractor.getSampleFlags();
                    trackIndex = extractor.getSampleTrackIndex();


                    muxer.writeSampleData(indexMap.get(trackIndex), dstBuf, bufferInfo);

                    //System.out.println(muxer);
                    extractor.advance();
                }
            }
        }

        muxer.stop();




        File file = new File(srcPath);
        file.delete();
    } catch (IllegalStateException e) {



        System.out.println("The source video file is malformed");


    } finally {


        muxer.release();

    }
//将MediaExtractor设置为从源代码读取。
MediaExtractor提取器=新的MediaExtractor();
setDataSource(srcPath);
int trackCount=extractor.getTrackCount();
System.out.println(“tracl”+trackCount);
//为目标设置MediaMuxer。
MediaMuxer-muxer;
muxer=newmediamuxer(dstPath,MediaMuxer.OutputFormat.muxer\u OUTPUT\u MPEG\u 4);
//设置磁道并检索选定磁道的最大缓冲区大小
//轨道。
HashMap indexMap=新的HashMap(trackCount);
int bufferSize=-1;
对于(int i=0;ibufferSize?newSize:bufferSize;
}
}
}
System.out.println(indexMap);
如果(缓冲区大小<0){
bufferSize=默认的缓冲区大小;
}
//设置提取器的方向和启动时间。
MediaMetadataRetriever retrieverSrc=新的MediaMetadataRetriever();
retrieverSrc.setDataSource(srcPath);
String degreesString=retrieverSrc.extractMetadata(
MediaMetadataRetriever.METADATA\u KEY\u VIDEO\u ROTATION);
if(degreesString!=null){
int度=整数.parseInt(degreesString);
如果(度>=0){
muxer.setOrientationHint(度);
}
}
如果(startMs>0){
提取器.seekTo(startMs*1000,MediaExtractor.SEEK\u至\u最近的\u同步);
}
//系统输出打印LN(提取器);
//将样本从MediaExtractor复制到MediaMuxer。我们将循环
//用于复制每个样本,并在到达源代码末尾时停止
//归档或超过修剪的结束时间。
整数偏移=0;
int trackIndex=-1;
ByteBuffer DSTBUFF=ByteBuffer.allocate(缓冲区大小);
MediaCodec.BufferInfo BufferInfo=新的MediaCodec.BufferInfo();
试一试{
muxer.start();
while(true){
系统输出打印项次(“复制”);
bufferInfo.offset=偏移量;
bufferInfo.size=提取器.readSampleData(dstBuf,偏移量);
如果(bufferInfo.size<0){
//InstabugSDKLogger.d(标签,“Saw输入EOS”);
System.out.println(“Saw输入EOS”);
bufferInfo.size=0;
打破
}否则{
/**
*缓冲区的表示时间戳(以微秒为单位)。
*这是从传入的表示时间戳派生的
*使用相应的输入缓冲区。对于
*0大小的缓冲区。
*/
/**
*返回当前样本的显示时间(以微秒为单位)。
*如果没有更多样本,则为-1。
*/
bufferInfo.presentationTimeUs=提取器.getSampleTime();
//1秒=1000000米秒
如果(endMs>0&&bufferInfo.presentationTimeUs>(endMs*1000)){
打破
}否则{
bufferInfo.flags=提取器.getSampleFlags();
trackIndex=extractor.getSampleTrackIndex();
muxer.writeSampleData(indexMap.get(trackIndex)、dstBuf、bufferInfo);
//系统输出打印LN(muxer);
提取器;
}
}
}
muxer.stop();
文件文件=新文件(srcPath);
delete();
}捕获(非法状态){
System.out.println(“源视频文件格式不正确”);
}最后{
muxer.release();
}

这可能是很多事情,但我看到时间戳后的第一个想法是,前3个视频样本中有2个出现了故障(就演示时间而言)。这对于某些格式来说是正常的,例如“H.264 main”。相反,这些样品是按合成时间排序的。由于
MediaExtractor/Muxer
似乎不支持合成时间,这让我相信您只能使用更简单的格式,例如“H.264基线”。如果你想证明我的理论,只需编写一个例程来转储所有的输入演示时间,看看它们是否严格有序。嘿@greeble31刚刚检查过。演示时间不按顺序排列。当订单中断时,它就崩溃了顺便问一下,你在测试什么版本的android?MediaMuxer只支持牛轧糖后的B帧。您好,先生,android版本是6。您的视频中有B帧,这意味着pts可能不会单调递增,这是自android牛轧糖后才支持的。你有3个选择,使用安卓7或更高版本