blob: e40ffea7708c8b8497d2fa85e6050843ee7e4e87 [file] [log] [blame]
Mauro Carvalho Chehab9cbfcd72016-07-17 19:43:22 -03001Cropping and Scaling algorithm, used in the sh_mobile_ceu_camera driver
2=======================================================================
3
4Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -03005
6Terminology
7-----------
8
9sensor scales: horizontal and vertical scales, configured by the sensor driver
10host scales: -"- host driver
11combined scales: sensor_scale * host_scale
12
13
14Generic scaling / cropping scheme
15---------------------------------
16
Mauro Carvalho Chehab9cbfcd72016-07-17 19:43:22 -030017.. code-block:: none
18
19 -1--
20 |
21 -2-- -\
22 | --\
23 | --\
24 +-5-- . -- -3-- -\
25 | `... -\
26 | `... -4-- . - -7..
27 | `.
28 | `. .6--
29 |
30 | . .6'-
31 | .´
32 | ... -4'- .´
33 | ...´ - -7'.
34 +-5'- .´ -/
35 | -- -3'- -/
36 | --/
37 | --/
38 -2'- -/
39 |
40 |
41 -1'-
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -030042
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -030043In the above chart minuses and slashes represent "real" data amounts, points and
Guennadi Liakhovetskid16290d2011-03-28 13:16:43 -030044accents represent "useful" data, basically, CEU scaled and cropped output,
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -030045mapped back onto the client's source plane.
46
47Such a configuration can be produced by user requests:
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -030048
49S_CROP(left / top = (5) - (1), width / height = (5') - (5))
50S_FMT(width / height = (6') - (6))
51
52Here:
53
54(1) to (1') - whole max width or height
55(1) to (2) - sensor cropped left or top
56(2) to (2') - sensor cropped width or height
57(3) to (3') - sensor scale
58(3) to (4) - CEU cropped left or top
59(4) to (4') - CEU cropped width or height
60(5) to (5') - reverse sensor scale applied to CEU cropped width or height
61(2) to (5) - reverse sensor scale applied to CEU cropped left or top
62(6) to (6') - CEU scale - user window
63
64
65S_FMT
66-----
67
68Do not touch input rectangle - it is already optimal.
69
701. Calculate current sensor scales:
71
Guennadi Liakhovetskid16290d2011-03-28 13:16:43 -030072 scale_s = ((2') - (2)) / ((3') - (3))
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -030073
742. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at
75current sensor scales onto input window - this is user S_CROP:
76
77 width_u = (5') - (5) = ((4') - (4)) * scale_s
78
793. Calculate new combined scales from "effective" input window to requested user
80window:
81
82 scale_comb = width_u / ((6') - (6))
83
844. Calculate sensor output window by applying combined scales to real input
85window:
86
Guennadi Liakhovetskid16290d2011-03-28 13:16:43 -030087 width_s_out = ((7') - (7)) = ((2') - (2)) / scale_comb
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -030088
895. Apply iterative sensor S_FMT for sensor output window.
90
91 subdev->video_ops->s_fmt(.width = width_s_out)
92
936. Retrieve sensor output window (g_fmt)
94
957. Calculate new sensor scales:
96
97 scale_s_new = ((3')_new - (3)_new) / ((2') - (2))
98
998. Calculate new CEU crop - apply sensor scales to previously calculated
100"effective" crop:
101
102 width_ceu = (4')_new - (4)_new = width_u / scale_s_new
103 left_ceu = (4)_new - (3)_new = ((5) - (2)) / scale_s_new
104
1059. Use CEU cropping to crop to the new window:
106
107 ceu_crop(.width = width_ceu, .left = left_ceu)
108
10910. Use CEU scaling to scale to the requested user window:
110
111 scale_ceu = width_ceu / width
112
113
114S_CROP
115------
116
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -0300117The API at http://v4l2spec.bytesex.org/spec/x1904.htm says:
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300118
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -0300119"...specification does not define an origin or units. However by convention
120drivers should horizontally count unscaled samples relative to 0H."
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300121
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -0300122We choose to follow the advise and interpret cropping units as client input
123pixels.
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300124
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -0300125Cropping is performed in the following 6 steps:
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300126
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -03001271. Request exactly user rectangle from the sensor.
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300128
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -03001292. If smaller - iterate until a larger one is obtained. Result: sensor cropped
130 to 2 : 2', target crop 5 : 5', current output format 6' - 6.
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300131
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -03001323. In the previous step the sensor has tried to preserve its output frame as
133 good as possible, but it could have changed. Retrieve it again.
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300134
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -03001354. Sensor scaled to 3 : 3'. Sensor's scale is (2' - 2) / (3' - 3). Calculate
136 intermediate window: 4' - 4 = (5' - 5) * (3' - 3) / (2' - 2)
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300137
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -03001385. Calculate and apply host scale = (6' - 6) / (4' - 4)
Guennadi Liakhovetski35b23b52009-12-11 11:34:20 -0300139
Guennadi Liakhovetskif7fc97a2010-03-23 11:42:32 -03001406. Calculate and apply host crop: 6 - 7 = (5 - 2) * (6' - 6) / (5' - 5)