davidliu

undo even scale changes

WebRTC m97 handles odd dimensions
... ... @@ -14,7 +14,6 @@ import io.livekit.android.room.DefaultsManager
import io.livekit.android.room.RTCEngine
import io.livekit.android.room.track.*
import io.livekit.android.room.util.EncodingUtils
import io.livekit.android.room.util.EncodingUtils.findEvenScaleDownBy
import io.livekit.android.util.LKLog
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.cancel
... ... @@ -323,7 +322,6 @@ internal constructor(
val midPreset = presets[1]
val lowPreset = presets[0]
fun addEncoding(videoEncoding: VideoEncoding, scale: Double) {
if (encodings.size >= EncodingUtils.VIDEO_RIDS.size) {
throw IllegalStateException("Attempting to add more encodings than we have rids for!")
... ... @@ -336,18 +334,19 @@ internal constructor(
// if resolution is high enough, we send both h and q res.
// otherwise only send h
val size = max(width, height)
fun calculateScaleDown(captureParam: VideoCaptureParameter): Double {
val targetSize = max(captureParam.width, captureParam.height)
return size / targetSize.toDouble()
}
if (size >= 960) {
var lowScale = findEvenScaleDownBy(width, height, lowPreset.capture.width, lowPreset.capture.height)
var midScale = findEvenScaleDownBy(width, height, midPreset.capture.width, midPreset.capture.height)
val lowScale = calculateScaleDown(lowPreset.capture)
val midScale = calculateScaleDown(midPreset.capture)
if (midScale == null || lowScale == null) {
lowScale = 4.0
midScale = 2.0
}
addEncoding(lowPreset.encoding, lowScale)
addEncoding(midPreset.encoding, midScale)
} else {
val lowScale = findEvenScaleDownBy(width, height, lowPreset.capture.width, lowPreset.capture.height) ?: 2.0
val lowScale = calculateScaleDown(lowPreset.capture)
addEncoding(lowPreset.encoding, lowScale)
}
addEncoding(encoding, 1.0)
... ...
... ... @@ -32,39 +32,6 @@ internal object EncodingUtils {
VideoPreset43.FHD
)
/**
* Encoders will often not be able to handle odd dimensions, so we should try to find a scale that will
* result in even dimensions.
*
* @return a scale that will result in dimensions that are both even, or null if none found.
*/
fun findEvenScaleDownBy(
sourceWidth: Int,
sourceHeight: Int,
targetWidth: Int,
targetHeight: Int,
): Double? {
fun Int.isEven() = this % 2 == 0
val sourceSize = min(sourceWidth, sourceHeight)
val targetSize = min(targetWidth, targetHeight)
for (i in 0..20) {
val scaleDownBy = sourceSize.toDouble() / (targetSize + i)
// Internally, WebRTC casts directly to int without rounding.
// https://github.com/webrtc-sdk/webrtc/blob/8c7139f8e6fa19ddf2c91510c177a19746e1ded3/media/engine/webrtc_video_engine.cc#L3676
val scaledWidth = (sourceWidth / scaleDownBy).toInt()
val scaledHeight = (sourceHeight / scaleDownBy).toInt()
if (scaledHeight.isEven() && scaledWidth.isEven()) {
return scaleDownBy
}
}
return null
}
fun determineAppropriateEncoding(width: Int, height: Int): VideoEncoding {
val presets = presetsForResolution(width, height)
... ...
package io.livekit.android.room.util
import org.junit.Assert
import org.junit.Test
class EncodingUtilsTest {
@Test
fun evenScale() {
fun Int.isEven() = this % 2 == 0
val sourceWidth = 800
val sourceHeight = 600
val scaleDownBy = EncodingUtils.findEvenScaleDownBy(sourceWidth, sourceHeight, 240, 180)
?: throw Exception("scale should not be null!")
Assert.assertTrue((sourceWidth / scaleDownBy).toInt().isEven())
Assert.assertTrue((sourceHeight / scaleDownBy).toInt().isEven())
}
@Test
fun evenScaleWeirdSource() {
fun Int.isEven() = this % 2 == 0
val sourceWidth = 800
val sourceHeight = 602
val scaleDownBy = EncodingUtils.findEvenScaleDownBy(sourceWidth, sourceHeight, 240, 180)
?: throw Exception("scale should not be null!")
Assert.assertTrue((sourceWidth / scaleDownBy).toInt().isEven())
Assert.assertTrue((sourceHeight / scaleDownBy).toInt().isEven())
}
}
\ No newline at end of file
... ...