我已使用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。
答案 0 :(得分:0)
我不确定这是否是错误的来源,但我认为在任意点将EOS
写入解码器缓冲区是不安全的。
原因是当输入视频使用H264 Main Profile或更高版本时, pts可能不是递增的顺序(因为存在B帧),所以你可能会错过视频结尾的几帧。 此外,当您发送到解码器的最后一帧是B帧时,解码器可能会期待下一个数据包,但您发送EOS标志并产生错误(不太确定)。
你可以做什么,你可以在到达你想要的帧后使用videoEncoder.signalEndOfInputStream()
向编码器发送EOS标志,(解码器输出的点数保证递增顺序,至少在android版本之后> = 4.3?)