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的一个实例。