简体   繁体   English

使用MediaCodec截断视频

[英]Truncate video with MediaCodec

I've used Android MediaCodec library to transcode video files (mainly change the resolution Sample code here ) 我使用Android MediaCodec库来转码视频文件(主要是在这里更改分辨率示例代码

Another thing I want to achieve is to truncate the video - to only take the beginning 15 seconds. 我想要实现的另一件事是截断视频 - 仅开始15秒。 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. 逻辑是检查videoExtractor.getSampleTime()是否大于15秒,我只是将EOS写入解码器缓冲区。

But I get an exception Caused by: android.media.MediaCodec$CodecException: Error 0xfffffff3 但我得到一个异常Caused by: android.media.MediaCodec$CodecException: Error 0xfffffff3

Here is my code: 这是我的代码:

        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 . 完整的源代码可以在这里找到。

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. 我不确定这是否是错误的来源,但我认为在任意点将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. 原因是当输入视频使用H264 Main Profile或更高版本时,pts可能不会按递增顺序(因为存在B帧),因此您可能会错过视频末尾的几帧。 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). 此外,当您发送到解码器的最后一帧是B帧时,解码器可能会期待下一个数据包,但您发送EOS标志并产生错误(不太确定)。

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 ?) 你可以做什么,你可以在你到达你想要的帧后使用videoEncoder.signalEndOfInputStream()将EOS标志发送到编码器,(解码器输出的pts保证按递增顺序,至少在android版本> = 4.3之后?)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM