1Cropping and Scaling algorithm, used in the sh_mobile_ceu_camera driver
2=======================================================================
3
4Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5
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
17.. 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'-
42
43In the above chart minuses and slashes represent "real" data amounts, points and
44accents represent "useful" data, basically, CEU scaled and cropped output,
45mapped back onto the client's source plane.
46
47Such a configuration can be produced by user requests:
48
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
72	scale_s = ((2') - (2)) / ((3') - (3))
73
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
87	width_s_out = ((7') - (7)) = ((2') - (2)) / scale_comb
88
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
117The API at http://v4l2spec.bytesex.org/spec/x1904.htm says:
118
119"...specification does not define an origin or units. However by convention
120drivers should horizontally count unscaled samples relative to 0H."
121
122We choose to follow the advise and interpret cropping units as client input
123pixels.
124
125Cropping is performed in the following 6 steps:
126
1271. Request exactly user rectangle from the sensor.
128
1292. 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.
131
1323. 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.
134
1354. 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)
137
1385. Calculate and apply host scale = (6' - 6) / (4' - 4)
139
1406. Calculate and apply host crop: 6 - 7 = (5 - 2) * (6' - 6) / (5' - 5)
141