使用MediaCodec截断视频

Qyl*_*lin 8 android mediacodec

我使用Android MediaCodec库来转码视频文件(主要是在这里更改分辨率示例代码)

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

但我得到一个例外 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;
        }
Run Code Online (Sandbox Code Playgroud)

完整的源代码可以在这里找到.

小智 1

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

原因是当输入视频使用 H264 Main Profile 或更高版本时,pts 可能不会按升序排列(因为 B 帧的存在),因此您可能会错过视频末尾的几帧。此外,当您发送到解码器的最后一帧是 B 帧时,解码器可能会期待下一个数据包,但您发送了 EOS 标志并产生错误(不太确定)。

不过,您可以做什么,您可以在达到所需帧后使用将 EOS 标志发送到编码器videoEncoder.signalEndOfInputStream(),(解码器输出的 pts 保证按递增顺序,至少在 android 版本 >= 4.3 之后?)