Browse Source

Request constrained AVC explicitly and diagnose hardware SPS limits

stream-multiview
evgeny 7 days ago
parent
commit
b01d54a431
  1. 18
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoCodec.kt

18
tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoCodec.kt

@ -23,7 +23,7 @@ internal class CallVideoCodec(val format: CallVideoFormat, val bitrate: Int, nam
try {
val media = MediaFormat.createVideoFormat(type.mime, format.width, format.height).apply {
setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible)
setInteger(MediaFormat.KEY_PROFILE, if (format.codec == 1) MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline
setInteger(MediaFormat.KEY_PROFILE, if (format.codec == 1) MediaCodecInfo.CodecProfileLevel.AVCProfileConstrainedBaseline
else MediaCodecInfo.CodecProfileLevel.HEVCProfileMain)
setInteger(MediaFormat.KEY_LEVEL, platformLevel(format.codec, format.level))
setInteger(MediaFormat.KEY_BIT_RATE, bitrate); setInteger(MediaFormat.KEY_FRAME_RATE, format.fps)
@ -122,11 +122,11 @@ internal class CallVideoCodec(val format: CallVideoFormat, val bitrate: Int, nam
try {
val f = CallVideoFormat(1, 1280, 720, codec = type.id, level = if (type.id == 1) 31 else 93)
val caps = entry.getCapabilitiesForType(type.mime)
if (!caps.videoCapabilities.areSizeAndRateSupported(1280, 720, 30.0)
|| !caps.encoderCapabilities.isBitrateModeSupported(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR)) continue
if (caps.videoCapabilities?.areSizeAndRateSupported(1280, 720, 30.0) != true
|| caps.encoderCapabilities?.isBitrateModeSupported(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR) != true) continue
CallVideoCodec(f, 1_000_000, entry.name).use { encoder ->
val packets = mutableListOf<Packet>(); var input = 0
val deadline = System.nanoTime() + 2_000_000_000
val deadline = System.nanoTime() + 5_000_000_000
while (packets.size < 4 && System.nanoTime() < deadline) {
if (input < 8 && encoder.submit(null, 1_000_000L + input * 33333, input == 0)) input++
packets += encoder.drain(); Thread.sleep(2)
@ -182,19 +182,21 @@ internal class CallVideoCodec(val format: CallVideoFormat, val bitrate: Int, nam
}
val bits = Bits(raw.toByteArray())
if (f.codec == 1) {
check(bits.read(8) == 66 && bits.read(8) and 64 != 0) { "AVC is not Constrained Baseline" }
check(bits.read(8) <= f.level); bits.ue(); bits.ue()
val profile = bits.read(8); val constraints = bits.read(8); val level = bits.read(8)
check(profile == 66 && constraints and 64 != 0) { "AVC profile=$profile constraints=$constraints level=$level SPS=${sps.joinToString { "%02x".format(it) }}" }
check(level <= f.level); bits.ue(); bits.ue()
when (bits.ue()) { 0 -> bits.ue(); 2 -> Unit; else -> error("Unsupported AVC POC") }
check(bits.ue() <= 1) { "AVC uses more than one reference" }
} else {
bits.read(4); check(bits.read(3) == 0) { "HEVC temporal layers" }; bits.read(1)
bits.read(2); check(bits.read(1) == 0 && bits.read(5) == 1) { "HEVC is not Main/Main tier" }
bits.read(2); val tier = bits.read(1); val profile = bits.read(5)
check(tier == 0 && profile == 1) { "HEVC profile=$profile tier=$tier SPS=${sps.joinToString { "%02x".format(it) }}" }
repeat(10) { bits.read(8) }; check(bits.read(8) <= f.level)
bits.ue(); check(bits.ue() == 1); bits.ue(); bits.ue()
if (bits.read(1) != 0) repeat(4) { bits.ue() }
check(bits.ue() == 0 && bits.ue() == 0); bits.ue(); bits.read(1)
val dpb = bits.ue(); check(bits.ue() == 0) { "HEVC reordered frames" }
check(dpb <= 1) { "HEVC requires more than two decoded pictures" }
check(dpb <= 1) { "HEVC decoded pictures=${dpb + 1} SPS=${sps.joinToString { "%02x".format(it) }}" }
}
}
}

Loading…
Cancel
Save