Android MediaCodec:编码时如何请求关键帧

在Android4.1中,实时编码应用程序经常需要关键帧。 但如何使用MediaCodec对象呢? 目前的Android4.2 SDK似乎不支持它。

排队输入缓冲区时, 可以通过指定MediaCodec.BUFFER_FLAG_SYNC_FRAME 产生随机关键帧:

MediaCodec codec = MediaCodec.createDecoderByType(type); codec.configure(format, ...); codec.start(); ByteBuffer[] inputBuffers = codec.getInputBuffers(); for (;;) { int inputBufferIndex = codec.dequeueInputBuffer(timeoutUs); if (inputBufferIndex >= 0) { // fill inputBuffers[inputBufferIndex] with valid data ... codec.queueInputBuffer(inputBufferIndex, 0, inputBuffers[inputBufferIndex].limit(), presentationTime, isKeyFrame ? MediaCodec.BUFFER_FLAG_SYNC_FRAME : 0); } } 

在Galaxy Nexus上编码视频时需要插入随机关键帧。 对此,MediaCodec在视频开始时不会自动生成关键帧。

配置编码器时,您可以通过设置KEY_I_FRAME_INTERVAL键来请求定期关键帧。 在下面的例子中,我要求每两秒钟一次。 为了清晰起见,我省略了其他键,如帧率或颜色格式,但是您仍然希望包含它们。

  encoder = MediaCodec.createByCodecName(codecInfo.getName()); MediaFormat inputFormat = MediaFormat.createVideoFormat(mimeType, width, height); /* ..... set various format options here ..... */ inputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2); encoder.configure(inputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); encoder.start(); 

不过,我怀疑你真正要问的是如何在编码时请求一个随机的关键帧,就像在剪切场景开始时一样。 不幸的是,我还没有看到一个接口。 停止并重新启动编码器可能会导致在重新启动时创建新的关键帧。 当我有机会尝试的时候,我会在这里公布结果。

我希望这是有帮助的。

Thad Phetteplace – GLACI,Inc.

MediaCodec有一个叫做setParameters的方法来解决这个问题。 在Kotlin你可以这样做:

 fun yieldKeyFrame(): Boolean { val param = Bundle() param.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0) try { videoEncoder.setParameters(param) return true } catch (e: IllegalStateException) { return false } } 

在上面的片段中, videoEncoder是配置为编码的MediaCodec的一个实例。