Drain accepted MediaCodec inputs before bitrate fallback replacement
This commit is contained in:
1 parent
0e53a9f5dd
commit
c0422a73c0
2 files changed
+24
-5
No files matched your search
@@ -24,6 +24,7 @@ internal class CallVideoCodec(requested: CallVideoFormat, bitrate: Int, val name
|
||||
private var partialFlags = 0
|
||||
private var preparing = false
|
||||
private var lastOutput = -1L
|
||||
private var lastInput = -1L
|
||||
var pendingFrames = 0
|
||||
private set
|
||||
|
||||
@@ -72,7 +73,7 @@ internal class CallVideoCodec(requested: CallVideoFormat, bitrate: Int, val name
|
||||
}
|
||||
}
|
||||
input.close(); codec.queueInputBuffer(index, 0, format.width * format.height * 3 / 2, pts, 0)
|
||||
pendingFrames++; return true
|
||||
lastInput = pts; pendingFrames++; return true
|
||||
}
|
||||
|
||||
/** Вызывается перед очередным IDR; подтверждение ядру — только после проверки этого IDR. */
|
||||
@@ -132,6 +133,23 @@ internal class CallVideoCodec(requested: CallVideoFormat, bitrate: Int, val name
|
||||
}
|
||||
return packets
|
||||
}
|
||||
/** Забрать все принятые входы перед заменой: EOS не требует новых кадров камеры. */
|
||||
fun finish(): List<Packet> {
|
||||
val packets = mutableListOf<Packet>(); val started = System.nanoTime(); var eos = false
|
||||
while (pendingFrames > 0 && System.nanoTime() - started < 2_000_000_000) {
|
||||
if (!eos) {
|
||||
val input = codec.dequeueInputBuffer(0)
|
||||
if (input >= 0) {
|
||||
codec.queueInputBuffer(input, 0, 0, lastInput + 1, MediaCodec.BUFFER_FLAG_END_OF_STREAM); eos = true
|
||||
}
|
||||
}
|
||||
packets += drain()
|
||||
if (pendingFrames > 0) Thread.sleep(1)
|
||||
}
|
||||
check(pendingFrames == 0) { "Encoder drain timeout name=$name pending=$pendingFrames" }
|
||||
LogManager.addLog("DEBUG", "call", "video encoder drained name=$name frames=${packets.size} us=${(System.nanoTime() - started) / 1000}")
|
||||
return packets
|
||||
}
|
||||
override fun close() {
|
||||
try { codec.stop() } catch (e: Exception) { LogManager.addLog("WARN", "call", "encoder stop: ${e.message}") }
|
||||
codec.release()
|
||||
|
||||
@@ -133,7 +133,7 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
|
||||
private fun fail(message: String) {
|
||||
LogManager.addLog("ERROR", "call", "video call=$id $message")
|
||||
wanted = wanted.copy(enabled = false); mutable.value = mutable.value.copy(settings = wanted, status = message)
|
||||
closeCamera(); encoder?.close(); encoder = null; active = null
|
||||
closeCamera(); encoder?.close(); encoder = null; pendingFrames.clear(); active = null
|
||||
if (confirmingRequest != 0L) CallVideoNative.applied(id, format?.generation ?: 0, confirmingRequest, 0)
|
||||
confirmingRequest = 0
|
||||
}
|
||||
@@ -249,6 +249,7 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
|
||||
// References сохранены: уже закодированные P-кадры остаются пригодны до нового KEY.
|
||||
confirmingRequest = requestId
|
||||
} else {
|
||||
drain(finish = true)
|
||||
old.close(); encoder = null
|
||||
try {
|
||||
encoder = CallVideoCodec(f, pendingRate, name)
|
||||
@@ -345,9 +346,9 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
|
||||
}, handler)
|
||||
} catch (e: Exception) { complete(); rejected("Camera session: ${e.message}") }
|
||||
}
|
||||
private fun drain() {
|
||||
private fun drain(finish: Boolean = false) {
|
||||
val codec = encoder ?: return; val f = format ?: return
|
||||
for (p in codec.drain()) {
|
||||
for (p in if (finish) codec.finish() else codec.drain()) {
|
||||
encodedBytes += p.bytes.size; encodedFrames++
|
||||
if (confirmingRequest != 0L && p.key && p.pts >= confirmingPts) {
|
||||
CallVideoNative.applied(id, f.generation, confirmingRequest, codec.bitrate); confirmingRequest = 0
|
||||
@@ -385,7 +386,7 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
|
||||
if (stopped) return
|
||||
stopped = true; player.stop(); CallVideoNative.close(id)
|
||||
handler.post {
|
||||
closeCamera(); encoder?.close(); encoder = null
|
||||
closeCamera(); encoder?.close(); encoder = null; pendingFrames.clear()
|
||||
preview.close(); previewTarget?.release(); previewTarget = null
|
||||
if (camera == null && !opening) thread.quitSafely()
|
||||
else handler.postDelayed({ thread.quitSafely() }, 3000)
|
||||
|
||||
Reference in new issue
Block a user