使用MediaCodec截断视频 [英] Truncate video with MediaCodec

查看:335
本文介绍了使用MediaCodec截断视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已使用Android MediaCodec库对视频文件进行转码(主要是更改分辨率此处的示例代码)

I've used Android MediaCodec library to transcode video files (mainly change the resolution Sample code here)

我要实现的另一件事是截断视频-仅花费开始的15秒.逻辑是检查videoExtractor.getSampleTime()是否大于15秒,我将EOS写入解码器缓冲区.

Another thing I want to achieve is to truncate the video - to only take the beginning 15 seconds. The logic is to check videoExtractor.getSampleTime() if it's greater than the 15 seconds, I'll just write an EOS to the decoder buffer.

但是我得到一个异常Caused by: android.media.MediaCodec$CodecException: Error 0xfffffff3

这是我的代码:

        while ((!videoEncoderDone) || (!audioEncoderDone)) {
        while (!videoExtractorDone
                && (encoderOutputVideoFormat == null || muxing)) {
            int decoderInputBufferIndex = videoDecoder.dequeueInputBuffer(TIMEOUT_USEC);
            if (decoderInputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER)
                break;

            ByteBuffer decoderInputBuffer = videoDecoderInputBuffers[decoderInputBufferIndex];
            int size = videoExtractor.readSampleData(decoderInputBuffer, 0);
            long presentationTime = videoExtractor.getSampleTime();

            if (size >= 0) {
                videoDecoder.queueInputBuffer(
                        decoderInputBufferIndex,
                        0,
                        size,
                        presentationTime,
                        videoExtractor.getSampleFlags());
            }
            videoExtractorDone = !videoExtractor.advance();

            if (!videoExtractorDone && videoExtractor.getSampleTime() > mVideoDurationLimit * 1000000) {
                videoExtractorDone = true;
            }

            if (videoExtractorDone)
                videoDecoder.queueInputBuffer(decoderInputBufferIndex,
                        0, 0, 0,  MediaCodec.BUFFER_FLAG_END_OF_STREAM);
            break;
        }

完整的源代码可以在此处找到.

The full source code can be found here.

推荐答案

我不确定这是否是错误的根源,但我认为在任意点将EOS写入解码器缓冲区并不安全.

I am not sure if this is the source of the error or not, but i think it is not safe write EOS to decoder buffer at arbitrary point.

原因是输入视频使用的是H264 Main Profile或更高版本, pt的顺序可能不是递增的(因为存在B帧),因此您可能会错过视频结尾处的几帧. 另外,当您发送给解码器的最后一帧是B帧时,解码器可能期待下一个数据包,但是您发送EOS标志并产生错误(不太确定).

The reason is when the input video is using H264 Main Profile or above, pts may not be in increasing order (because the existence of B-frame) so you may miss several frames at the end of the video. Also, when the last frame you send to the decoder is B-frame, decoder might be expecting the next packet but you send the EOS flag and produce error (not quite sure).

但是,您可以执行以下操作:到达所需的帧后,可以使用videoEncoder.signalEndOfInputStream()将EOS标志发送到编码器((至少在android版本> =之后,解码器的输出pts被保证按升序排列) 4.3?)

What you can do though, you can send EOS flag to the encoder using videoEncoder.signalEndOfInputStream() after you reach your desired frame, (pts of the output of decoder is guaranted to be in increasing order, at least after android version >= 4.3 ?)

这篇关于使用MediaCodec截断视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆