在没有新数据可用时处理异步 MediaCodec 中的可用输入缓冲区以进行解码

Handling available input buffers in async MediaCodec for decoding when no new data is available

我正在使用异步 Android MediaCodec 解码通过 websocket 接收的 H.264 视频数据。

我的问题是当没有新的编码数据要解码时如何处理输入缓冲区?

目前,当没有来自 websocket 的新编码数据时,我在没有任何数据的情况下对输入缓冲区进行排队:

override fun onInputBufferAvailable(codec: MediaCodec, index: Int) {
    if (videoFrames.isNotEmpty()) {
        val inputBuffer = codec.getInputBuffer(index)
        inputBuffer?.put(videoFrames.removeFirst())
        codec.queueInputBuffer(index, 0, currentFrame.size, 0, 0)
    } else {
        codec.queueInputBuffer(index, 0, 0, 0, 0)
    }
}

其中 videoFrames 是包含编码视频数据的帧列表。

我像上面那样做,因为如果我选择删除 else 子句并且不对空输入缓冲区进行排队,输入缓冲区将永远不会再次可用。

是否有不同的处理方式?我觉得把一个空的输入缓冲区排队是不对的。

另一种似乎可以稍微提高解码器性能的解决方案是将可用的输入缓冲区存储在队列中,并在收到新的编码视频数据时获取它们。类似于以下内容:

val videoFrames = ConcurrentList<ByteArray>()
val availableBuffers = mutableListOf<Int>()
var decoder: MediaCodec? = null

fun onInputBufferAvailable(codec: MediaCodec, index: Int) {
    availableBuffers.add(index)
}

fun processFrame(frame: ByteArray) {
    var frameToProcess = frame

    if (videoFrames.isNotEmpty()) {
        videoFrames.add(frame)
        frameToProcess = videoFrames.removeFirst()
    }

    if (availableBuffers.isNotEmpty() && decoder != null) {
        val bufferIndex = availableBuffers.removeFirst()
        val inputBuffer = decoder!!.getInputBuffer(bufferIndex)

        inputBuffer?.put(frameToProcess)
        decoder!!.queueInputBuffer(bufferIndex, 0, frameToProcess.size, 0, 0)
    }
}