Browse Source

Retain complete codec parameter sets across separate configuration callbacks

master
evgeny 6 days ago
parent
commit
990713c7a7
  1. 3
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamCaptureEngine.kt
  2. 11
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamVideoCodec.kt
  3. 7
      tools/chatgui-android/app/src/test/java/com/utun/chat/data/StreamVideoCodecTest.kt

3
tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamCaptureEngine.kt

@ -166,8 +166,7 @@ class StreamCaptureEngine(
buffer.position(info.offset); buffer.limit(info.offset + info.size) buffer.position(info.offset); buffer.limit(info.offset + info.size)
val bytes = ByteArray(info.size).also { buffer.get(it) } val bytes = ByteArray(info.size).also { buffer.get(it) }
if (info.flags and MediaCodec.BUFFER_FLAG_CODEC_CONFIG != 0) { if (info.flags and MediaCodec.BUFFER_FLAG_CODEC_CONFIG != 0) {
val codecConfig = mode.videoCodec.normalize(bytes) csd = mode.videoCodec.mergeConfig(csd, bytes)
check(codecConfig.size <= StreamVideoCodec.MAX_CONFIG); csd = codecConfig
} else encoded(bytes, info, config, rotation, token) } else encoded(bytes, info, config, rotation, token)
} }
if (info.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM != 0) problem = "unexpected encoder EOS" if (info.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM != 0) problem = "unexpected encoder EOS"

11
tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamVideoCodec.kt

@ -21,6 +21,17 @@ enum class StreamVideoCodec(val id: Int, val label: String, val mime: String, va
require(bytes.isNotEmpty() && bytes.size <= H264AnnexB.MAX_FRAME) require(bytes.isNotEmpty() && bytes.size <= H264AnnexB.MAX_FRAME)
return if (annexB) H264AnnexB.normalize(bytes) else bytes.copyOf() return if (annexB) H264AnnexB.normalize(bytes) else bytes.copyOf()
} }
/** Parameter sets могут прийти отдельными CODEC_CONFIG callbacks; сохраняем полный набор текущей revision. */
fun mergeConfig(previous: ByteArray, update: ByteArray): ByteArray {
val next = normalize(update)
val result = if (!annexB || previous.isEmpty()) next else {
val units = H264AnnexB.nals(previous).map { it.second }.toMutableList()
for ((_, unit) in H264AnnexB.nals(next)) if (units.none { it.contentEquals(unit) }) units += unit
units.fold(byteArrayOf()) { a, unit -> a + unit }
}
require(result.size <= MAX_CONFIG)
return result
}
private fun nalTypes(bytes: ByteArray): Set<Int> = H264AnnexB.nals(bytes).map { (_, nal) -> private fun nalTypes(bytes: ByteArray): Set<Int> = H264AnnexB.nals(bytes).map { (_, nal) ->
val at = if (nal[2] == 1.toByte()) 3 else 4 val at = if (nal[2] == 1.toByte()) 3 else 4
when (this) { when (this) {

7
tools/chatgui-android/app/src/test/java/com/utun/chat/data/StreamVideoCodecTest.kt

@ -22,6 +22,13 @@ class StreamVideoCodecTest {
val decoded = StreamVideoCodec.VP9.unpackKey(StreamVideoCodec.VP9.keyFrame(byteArrayOf(1), byteArrayOf())) val decoded = StreamVideoCodec.VP9.unpackKey(StreamVideoCodec.VP9.keyFrame(byteArrayOf(1), byteArrayOf()))
assertTrue(decoded.first.isEmpty()); assertArrayEquals(byteArrayOf(1), decoded.second) assertTrue(decoded.first.isEmpty()); assertArrayEquals(byteArrayOf(1), decoded.second)
} }
@Test fun separateParameterSetsRemainCompleteWithoutDuplicates() {
val sps = nal(0x67, 1); val pps = nal(0x68, 2)
val config = StreamVideoCodec.H264.mergeConfig(sps, pps)
assertArrayEquals(sps + pps, config)
assertArrayEquals(config, StreamVideoCodec.H264.mergeConfig(config, sps))
StreamVideoCodec.H264.unpackKey(StreamVideoCodec.H264.keyFrame(nal(0x65, 3), config))
}
@Test fun codecAndBitrateSurviveCameraModeSelection() { @Test fun codecAndBitrateSurviveCameraModeSelection() {
val base = StreamCaptureMode("a", 1280, 720, 30, 30, false, "encoder", 2_000_000) val base = StreamCaptureMode("a", 1280, 720, 30, 30, false, "encoder", 2_000_000)
val hevc = base.copy(videoCodec = StreamVideoCodec.H265, minimumBitrate = 500000, maximumBitrate = 3000000) val hevc = base.copy(videoCodec = StreamVideoCodec.H265, minimumBitrate = 500000, maximumBitrate = 3000000)

Loading…
Cancel
Save