【问题标题】:Truncate video with MediaCodec使用 MediaCodec 截断视频
【发布时间】:2017-01-26 20:34:51
【问题描述】:

我用过Android MediaCodec库对视频文件进行转码(主要是改分辨率Sample code here

我想要实现的另一件事是截断视频 - 只占用开始的 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;
        }

完整的源代码可以在here找到。

【问题讨论】:

  • 如果您愿意,请查看Google's ExoPlayer。它有更简单的 API
  • 你能发布完整的 logcat 输出吗?
  • @crocodilys exoplayer 只是一个玩家吗?我不认为它可以转码视频。我错了吗?
  • @willis 感谢您的回复。我认为整个想法是不正确的。实际上我使用的是 OSS android-transcoder。它比原始 api 好得多。我想说主要的收获是性能。转码时间从 11 秒提升到 5~6 秒。
  • 我更喜欢你的 ffmpeg。请在此处查看答案,stackoverflow.com/a/38299320/3992798

标签: android android-mediacodec


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-19
    • 2016-03-12
    • 1970-01-01
    • 1970-01-01
    • 2016-02-25
    • 2016-04-25
    • 1970-01-01
    • 2020-03-21
    相关资源
    最近更新 更多