fix:调整渲染缓冲区

This commit is contained in:
liyi 2025-06-23 15:30:08 +08:00
parent c97f719ccb
commit 6e44ee8b48

View File

@ -80,7 +80,7 @@ class VideoDecoder(
// 渲染帧率fps可由外部控制默认30 // 渲染帧率fps可由外部控制默认30
@Volatile @Volatile
var renderFps: Int = 25 var renderFps: Int = 20
// 兜底记录最近一次I帧的frameSeqP/B帧依赖校验 // 兜底记录最近一次I帧的frameSeqP/B帧依赖校验
@Volatile @Volatile
@ -111,6 +111,10 @@ class VideoDecoder(
private val reorderLock = ReentrantLock() // 线程安全 private val reorderLock = ReentrantLock() // 线程安全
private val MAX_REORDER_BUFFER_SIZE = BUFFER_QUEUE_CAPACITY private val MAX_REORDER_BUFFER_SIZE = BUFFER_QUEUE_CAPACITY
// 低水位启动渲染标志
@Volatile
private var renderStarted = false
// 输入帧结构体 // 输入帧结构体
private data class FrameData( private data class FrameData(
val data: ByteArray, val data: ByteArray,
@ -161,6 +165,39 @@ class VideoDecoder(
// 创建解码器 // 创建解码器
val decoder = MediaCodec.createDecoderByType(mime) val decoder = MediaCodec.createDecoderByType(mime)
// ========== 输出所有支持的视频解码器及类型 ==========
try {
val codecList = if (android.os.Build.VERSION.SDK_INT >= 21) {
android.media.MediaCodecList(android.media.MediaCodecList.ALL_CODECS).codecInfos
} else {
arrayOf<android.media.MediaCodecInfo>()
}
Log.i(TAG, "[CodecList] 支持的视频解码器如下:")
for (info in codecList) {
if (!info.isEncoder) {
val types = info.supportedTypes.joinToString(", ")
val name = info.name
val isHardware = if (android.os.Build.VERSION.SDK_INT >= 29) info.isHardwareAccelerated else !name.startsWith("OMX.google.")
val isSoftware = if (android.os.Build.VERSION.SDK_INT >= 29) info.isSoftwareOnly else name.startsWith("OMX.google.")
Log.i(TAG, "解码器名称: $name, 支持类型: [$types], 硬解码: $isHardware, 软解码: $isSoftware")
}
}
} catch (e: Exception) {
Log.w(TAG, "[CodecList] 获取解码器列表失败", e)
}
// ========== 输出当前创建的解码器类型 ==========
try {
val codecInfo = decoder.codecInfo
val name = codecInfo.name
val isHardware = if (android.os.Build.VERSION.SDK_INT >= 29) codecInfo.isHardwareAccelerated else !name.startsWith("OMX.google.")
val isSoftware = if (android.os.Build.VERSION.SDK_INT >= 29) codecInfo.isSoftwareOnly else name.startsWith("OMX.google.")
Log.i(TAG, "[CurrentCodec] 当前解码器: $name, 硬解码: $isHardware, 软解码: $isSoftware")
} catch (e: Exception) {
Log.w(TAG, "[CurrentCodec] 获取当前解码器信息失败", e)
}
// 设置解码回调 // 设置解码回调
decoder.setCallback(object : MediaCodec.Callback() { decoder.setCallback(object : MediaCodec.Callback() {
override fun onInputBufferAvailable(codec: MediaCodec, index: Int) { override fun onInputBufferAvailable(codec: MediaCodec, index: Int) {
@ -237,6 +274,17 @@ class VideoDecoder(
return@Runnable return@Runnable
} }
// 低水位启动渲染逻辑
if (!renderStarted) {
if (outputFrameQueue.size >= (BUFFER_QUEUE_CAPACITY * 0.15).toInt()) {
renderStarted = true
Log.i(TAG, "[Render] 渲染启动outputFrameQueue已达低水位: ${outputFrameQueue.size}")
} else {
// 未达到低水位前不渲染
return@Runnable
}
}
val frame = outputFrameQueue.poll() val frame = outputFrameQueue.poll()
if (frame != null) { if (frame != null) {
frame.codec.releaseOutputBuffer(frame.bufferIndex, true) frame.codec.releaseOutputBuffer(frame.bufferIndex, true)
@ -247,10 +295,10 @@ class VideoDecoder(
mainHandler.post { onFrameRendered() } mainHandler.post { onFrameRendered() }
hasNotifiedFlutter = true hasNotifiedFlutter = true
} }
// Log.d(TAG, "[Render] 渲染: bufferIdx=${frame.bufferIndex}, pts=${frame.timestampUs}, " + Log.d(TAG, "[Render] 渲染: bufferIdx=${frame.bufferIndex}, pts=${frame.timestampUs}, " +
// "当前outputFrameQueue=${outputFrameQueue.size}") "当前outputFrameQueue=${outputFrameQueue.size}")
} else { } else {
// Log.w(TAG, "[Render] 渲染空转无帧可渲染当前outputFrameQueue=${outputFrameQueue.size}") Log.w(TAG, "[Render] 渲染空转无帧可渲染当前outputFrameQueue=${outputFrameQueue.size}")
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "[RenderTask] Exception", e) Log.e(TAG, "[RenderTask] Exception", e)
@ -275,10 +323,10 @@ class VideoDecoder(
refIFrameSeq: Int? refIFrameSeq: Int?
): Boolean { ): Boolean {
if (!running || mediaCodec == null) return false if (!running || mediaCodec == null) return false
if (!frameSeqSet.add(frameSeq)) { // if (!frameSeqSet.add(frameSeq)) {
Log.w(TAG, "[decodeFrame] 丢弃重复帧: type=$frameType, seq=$frameSeq, refI=$refIFrameSeq, ts=$timestamp") // Log.w(TAG, "[decodeFrame] 丢弃重复帧: type=$frameType, seq=$frameSeq, refI=$refIFrameSeq, ts=$timestamp")
return false // 防止重复帧 // return false // 防止重复帧
} // }
// 2. 初始化起点 // 2. 初始化起点
if (timestampBaseMs == null) { if (timestampBaseMs == null) {
synchronized(this) { synchronized(this) {