/// AV1 normative horizontal super-resolution. Phase uses visible plane widths;
/// tap availability includes reconstructed MI padding. The same phase advances
/// across a complete row, independent of coding-tile boundaries.
///|
let av1_superres_filters : Array[Array[Int]] = [
[0, 0, 0, 128, 0, 0, 0, 0],
[0, 0, -1, 128, 2, -1, 0, 0],
[0, 1, -3, 127, 4, -2, 1, 0],
[0, 1, -4, 127, 6, -3, 1, 0],
[0, 2, -6, 126, 8, -3, 1, 0],
[0, 2, -7, 125, 11, -4, 1, 0],
[-1, 2, -8, 125, 13, -5, 2, 0],
[-1, 3, -9, 124, 15, -6, 2, 0],
[-1, 3, -10, 123, 18, -6, 2, -1],
[-1, 3, -11, 122, 20, -7, 3, -1],
[-1, 4, -12, 121, 22, -8, 3, -1],
[-1, 4, -13, 120, 25, -9, 3, -1],
[-1, 4, -14, 118, 28, -9, 3, -1],
[-1, 4, -15, 117, 30, -10, 4, -1],
[-1, 5, -16, 116, 32, -11, 4, -1],
[-1, 5, -16, 114, 35, -12, 4, -1],
[-1, 5, -17, 112, 38, -12, 4, -1],
[-1, 5, -18, 111, 40, -13, 5, -1],
[-1, 5, -18, 109, 43, -14, 5, -1],
[-1, 6, -19, 107, 45, -14, 5, -1],
[-1, 6, -19, 105, 48, -15, 5, -1],
[-1, 6, -19, 103, 51, -16, 5, -1],
[-1, 6, -20, 101, 53, -16, 6, -1],
[-1, 6, -20, 99, 56, -17, 6, -1],
[-1, 6, -20, 97, 58, -17, 6, -1],
[-1, 6, -20, 95, 61, -18, 6, -1],
[-2, 7, -20, 93, 64, -18, 6, -2],
[-2, 7, -20, 91, 66, -19, 6, -1],
[-2, 7, -20, 88, 69, -19, 6, -1],
[-2, 7, -20, 86, 71, -19, 6, -1],
[-2, 7, -20, 84, 74, -20, 7, -2],
[-2, 7, -20, 81, 76, -20, 7, -1],
[-2, 7, -20, 79, 79, -20, 7, -2],
[-1, 7, -20, 76, 81, -20, 7, -2],
[-2, 7, -20, 74, 84, -20, 7, -2],
[-1, 6, -19, 71, 86, -20, 7, -2],
[-1, 6, -19, 69, 88, -20, 7, -2],
[-1, 6, -19, 66, 91, -20, 7, -2],
[-2, 6, -18, 64, 93, -20, 7, -2],
[-1, 6, -18, 61, 95, -20, 6, -1],
[-1, 6, -17, 58, 97, -20, 6, -1],
[-1, 6, -17, 56, 99, -20, 6, -1],
[-1, 6, -16, 53, 101, -20, 6, -1],
[-1, 5, -16, 51, 103, -19, 6, -1],
[-1, 5, -15, 48, 105, -19, 6, -1],
[-1, 5, -14, 45, 107, -19, 6, -1],
[-1, 5, -14, 43, 109, -18, 5, -1],
[-1, 5, -13, 40, 111, -18, 5, -1],
[-1, 4, -12, 38, 112, -17, 5, -1],
[-1, 4, -12, 35, 114, -16, 5, -1],
[-1, 4, -11, 32, 116, -16, 5, -1],
[-1, 4, -10, 30, 117, -15, 4, -1],
[-1, 3, -9, 28, 118, -14, 4, -1],
[-1, 3, -9, 25, 120, -13, 4, -1],
[-1, 3, -8, 22, 121, -12, 4, -1],
[-1, 3, -7, 20, 122, -11, 3, -1],
[-1, 2, -6, 18, 123, -10, 3, -1],
[0, 2, -6, 15, 124, -9, 3, -1],
[0, 2, -5, 13, 125, -8, 2, -1],
[0, 1, -4, 11, 125, -7, 2, 0],
[0, 1, -3, 8, 126, -6, 2, 0],
[0, 1, -3, 6, 127, -4, 1, 0],
[0, 1, -2, 4, 127, -3, 1, 0],
[0, 0, -1, 2, 128, -1, 0, 0],
]
///|
/// Q14 step and initial phase from the normative integer equations. Division
/// of negative values truncates toward zero, including the error correction.
/// The caller handles equal-width frames without invoking the active scaler.
fn av1_superres_params(
downscaled_width : Int,
upscaled_width : Int,
) -> (Int, Int)? {
if downscaled_width <= 0 ||
downscaled_width > 65536 ||
upscaled_width <= downscaled_width ||
upscaled_width > 65536 ||
upscaled_width > 2 * downscaled_width {
return None
}
let step = ((downscaled_width << 14) + upscaled_width / 2) / upscaled_width
let error = upscaled_width * step - (downscaled_width << 14)
let initial = (
-((upscaled_width - downscaled_width) << 13) + upscaled_width / 2
) /
upscaled_width +
128 -
error / 2
Some((step, initial & 16383))
}
///|
/// Produce packed visible output rows from strided reconstructed input. Values
/// between `src_available_width` and `src_stride` are storage padding and are
/// never sampled. Available MI pixels beyond `downscaled_width` remain valid
/// filter inputs; only the outer frame edges repeat their last sample.
fn av1_superres_upscale_plane(
src : Array[Int],
src_stride : Int,
src_available_width : Int,
downscaled_width : Int,
upscaled_width : Int,
rows : Int,
bit_depth : Int,
) -> Array[Int]? {
let (step, initial) = match
av1_superres_params(downscaled_width, upscaled_width) {
Some(value) => value
None => return None
}
if rows <= 0 ||
rows > 65536 ||
src_available_width < downscaled_width ||
src_available_width > 65536 ||
src_stride < src_available_width ||
src.length() < src_available_width ||
rows - 1 > (src.length() - src_available_width) / src_stride ||
upscaled_width > MAX_IMAGE_PIXELS / rows ||
(bit_depth != 8 && bit_depth != 10 && bit_depth != 12) {
return None
}
let maximum = (1 << bit_depth) - 1
for row in 0.. maximum {
return None
}
}
}
let output = Array::make(upscaled_width * rows, 0)
for row in 0..> 14
let phase = (position & 16383) >> 8
let filter = av1_superres_filters[phase]
let mut sum = 0
for tap in 0..<8 {
let x = integer + tap - 3
let x = if x < 0 {
0
} else if x >= src_available_width {
src_available_width - 1
} else {
x
}
sum = sum + src[row * src_stride + x] * filter[tap]
}
output[row * upscaled_width + col] = av1_intra_clip(
(sum + 64) >> 7,
bit_depth,
)
position = position + step
}
}
Some(output)
}