转码 H264 MP4 时重复帧=冻结效果会产生奇怪的伪影

问题描述

我试图通过在 Java / Android 平台上将 H264 视频转码为 H264 视频时重复几秒钟相同的输入帧来实现定格效果。我修改https://github.com/ypresto/android-transcoder/blob/master/lib/src/main/java/net/ypresto/androidtranscoder/engine/VideoTrackTranscoder.java 以便我直接跳过 android MediaExtractor.advance()

if(timeScaler.frozenAt==-1 ){
     mediaExtractor.advance();
}
else{
    freezeUsec +=  (1000/outputFormat.getInteger(MediaFormat.KEY_FRAME_RATE)) *1000;
    return DRAIN_STATE_NONE;
}
return DRAIN_STATE_CONSUMED;

效果激活时。我的想法是,这只会使解码器和编码器重复相同的数据,从而产生所需的效果。这很有效,但我在冻结效果后的帧中得到了奇怪的(压缩?)伪影。看起来冻结框架的部分(手臂 + 球)卡住了几秒钟。在某些设备上效果很小,而在其他设备上效果很差(如下图所示):

MP4 artefacts

解决方法

在 H.264 中,视频数据流中只有一小部分帧是所谓的 I 帧,也称为关键帧或瞬时解码器刷新 (IDR) 帧。其余的是 P(预测)帧或 B(内插)帧。换句话说,每个解码的帧都依赖于前一帧。

如果你抑制 P 或 B 帧的解码,或者重复解码它们,你会损坏你的解码图片,直到下一个 I 帧出现。