[PATCH] media: dw100: Rectify rounding error

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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));
-- 
2.45.2





[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux