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