Hi Umang,
Thanks for the patch. Nice catch.
On 10/25/24 3:03 PM, Umang Jain wrote:
From: Stefan Klug <stefan.klug@xxxxxxxxxxxxxxxx>
The current scaler code fails in many cases which can be validated
by the following python script:
```
error_count = 0
valid_count = 0
def check_scaling_error(src_w, dst_w, add_point_five):
global error_count
global valid_count
qscale = (dst_w << 16) // src_w
if (add_point_five):
delta = 1 << 15; # 0.5 in Q16.16
else:
delta = 0
scaled_w = ((((src_w << 16) + delta) * qscale) >> 32)
if dst_w != scaled_w:
print(f'scale_error: src_w: {src_w} | dst_w:{dst_w} | scaled_w:{scaled_w}')
error_count += 1
else:
valid_count += 1
print(f'==== Test without delta=0.5 ====\n')
for i in range(1000, 1920):
check_scaling_error(1920, i, False)
print(f'Error: {error_count} | Valid: {valid_count}\n\n')
error_count = 0
print(f'==== Test with delta=0.5 ====')
for i in range(1000, 1920):
check_scaling_error(1920, i, True)
print(f'Error: {error_count} | Valid: {valid_count}\n\n')
```
Excerpt of the output is retrieved:
```
==== Test without delta=0.5 ====
...
...
scale_error: src_w: 1920 | dst_w:1915 | scaled_w:1914
scale_error: src_w: 1920 | dst_w:1916 | scaled_w:1915
scale_error: src_w: 1920 | dst_w:1917 | scaled_w:1916
scale_error: src_w: 1920 | dst_w:1918 | scaled_w:1917
scale_error: src_w: 1920 | dst_w:1919 | scaled_w:1918
Error: 859 | Valid: 61
==== Test with delta=0.5 ====
Error: 0 | Valid: 981
```
Hence, fixing the scaling rounding error by adding 0.5 to the
frame dimensions before applying the scale.
Signed-off-by: Stefan Klug <stefan.klug@xxxxxxxxxxxxxxxx>
Signed-off-by: Umang Jain <umang.jain@xxxxxxxxxxxxxxxx>
---
drivers/media/platform/nxp/dw100/dw100.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/nxp/dw100/dw100.c b/drivers/media/platform/nxp/dw100/dw100.c
index 42712ccff754..541706f0aec4 100644
--- a/drivers/media/platform/nxp/dw100/dw100.c
+++ b/drivers/media/platform/nxp/dw100/dw100.c
@@ -984,6 +984,7 @@ static int dw100_s_selection(struct file *file, void *fh,
u32 qscalex, qscaley, qscale;
int x, y, w, h;
unsigned int wframe, hframe;
+ uint32_t zero_point_five;
if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
return -EINVAL;
@@ -1032,8 +1033,9 @@ static int dw100_s_selection(struct file *file, void *fh,
}
}
- w = (u32)((((u64)wframe << 16) * qscale) >> 32);
- h = (u32)((((u64)hframe << 16) * qscale) >> 32);
+ zero_point_five = 1 << 15;
+ w = (u32)(((((u64)wframe << 16)+zero_point_five) * qscale) >> 32);
+ h = (u32)(((((u64)hframe << 16)+zero_point_five) * qscale) >> 32);
x = x + (sel->r.width - w) / 2;
y = y + (sel->r.height - h) / 2;
x = min(wframe - w, (unsigned int)max(0, x));
Reviewed-by: Xavier Roumegue <xavier.roumegue@xxxxxxxxxxx>