Browse Source

Use available encoder profiles when the preferred video profile is absent

master
evgeny 6 days ago
parent
commit
499ce21cfc
  1. 9
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamCameraModes.kt
  2. 2
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamCaptureEngine.kt
  3. 1
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamVideoCodec.kt

9
tools/chatgui-android/app/src/main/java/com/utun/chat/data/StreamCameraModes.kt

@ -11,7 +11,8 @@ import android.os.Build
data class StreamCaptureMode(val camera: String, val width: Int, val height: Int, val fps: Int,
val minimumFps: Int, val highSpeed: Boolean, val codec: String, val bitrate: Int,
val videoCodec: StreamVideoCodec = StreamVideoCodec.H264,
val minimumBitrate: Int = 1, val maximumBitrate: Int = Int.MAX_VALUE) {
val minimumBitrate: Int = 1, val maximumBitrate: Int = Int.MAX_VALUE,
val encoderProfile: Int? = videoCodec.profile) {
val label get() = "${width}×${height} · $fps fps"
}
data class StreamCamera(val id: String, val lens: LensOption, val modes: List<StreamCaptureMode>)
@ -39,14 +40,14 @@ object StreamCameraModes {
if (highSpeed && Build.VERSION.SDK_INT >= 29 && !codec.isHardwareAccelerated) continue
val caps = codec.getCapabilitiesForType(type.mime)
val video = caps.videoCapabilities
val profile = type.encoderProfile(caps.profileLevels.map { it.profile }.toIntArray())
if (!caps.colorFormats.contains(MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface) ||
(type.profile != null && caps.profileLevels.none { it.profile == type.profile }) ||
!video.areSizeAndRateSupported(width, height, fps.toDouble())) continue
val bitrate = (width.toLong() * height * fps / 14).coerceIn(512_000L, 16_000_000L).toInt()
modes.add(StreamCaptureMode(lens.cameraId, width, height, fps, lower, highSpeed, codec.name,
video.bitrateRange.clamp(bitrate), type, video.bitrateRange.lower, video.bitrateRange.upper))
video.bitrateRange.clamp(bitrate), type, video.bitrateRange.lower, video.bitrateRange.upper, profile))
LogManager.addLog("INFO", "video", "camera mode camera=${lens.cameraId} ${width}x$height fps=$lower..$fps " +
"highSpeed=$highSpeed type=${type.label} encoder=${codec.name} bitrate=${modes.last().bitrate} " +
"highSpeed=$highSpeed type=${type.label} encoder=${codec.name} profile=$profile bitrate=${modes.last().bitrate} " +
"range=${video.bitrateRange} achievable=${video.getAchievableFrameRatesFor(width, height)}")
break
} catch (e: Exception) { LogManager.addLog("WARN", "video", "codec probe ${codec.name}: ${e.message}") }

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

@ -138,7 +138,7 @@ class StreamCaptureEngine(
if (switchStartedNs == 0L) switchStartedNs = reportNs
val format = MediaFormat.createVideoFormat(mode.videoCodec.mime, mode.width, mode.height).apply {
setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
mode.videoCodec.profile?.let { setInteger(MediaFormat.KEY_PROFILE, it) }
mode.encoderProfile?.let { setInteger(MediaFormat.KEY_PROFILE, it) }
setInteger(MediaFormat.KEY_BIT_RATE, config.bitrate)
setInteger(MediaFormat.KEY_FRAME_RATE, mode.fps); setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1)
if (Build.VERSION.SDK_INT >= 29) setInteger(MediaFormat.KEY_MAX_B_FRAMES, 0)

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

@ -21,6 +21,7 @@ enum class StreamVideoCodec(val id: Int, val label: String, val mime: String, va
require(bytes.isNotEmpty() && bytes.size <= H264AnnexB.MAX_FRAME)
return if (annexB) H264AnnexB.normalize(bytes) else bytes.copyOf()
}
fun encoderProfile(available: IntArray): Int? = profile?.takeIf { it in available } ?: available.firstOrNull()
/** Parameter sets могут прийти отдельными CODEC_CONFIG callbacks; сохраняем полный набор текущей revision. */
fun mergeConfig(previous: ByteArray, update: ByteArray): ByteArray {
val next = normalize(update)

Loading…
Cancel
Save