Based on kernel version 4.7.2. Page generated on 2016-08-22 22:48 EST.
1 Cropping and Scaling algorithm, used in the sh_mobile_ceu_camera driver 2 ======================================================================= 3 4 Terminology 5 ----------- 6 7 sensor scales: horizontal and vertical scales, configured by the sensor driver 8 host scales: -"- host driver 9 combined scales: sensor_scale * host_scale 10 11 12 Generic scaling / cropping scheme 13 --------------------------------- 14 15 -1-- 16 | 17 -2-- -\ 18 | --\ 19 | --\ 20 +-5-- . -- -3-- -\ 21 | `... -\ 22 | `... -4-- . - -7.. 23 | `. 24 | `. .6-- 25 | 26 | . .6'- 27 | .´ 28 | ... -4'- .´ 29 | ...´ - -7'. 30 +-5'- .´ -/ 31 | -- -3'- -/ 32 | --/ 33 | --/ 34 -2'- -/ 35 | 36 | 37 -1'- 38 39 In the above chart minuses and slashes represent "real" data amounts, points and 40 accents represent "useful" data, basically, CEU scaled and cropped output, 41 mapped back onto the client's source plane. 42 43 Such a configuration can be produced by user requests: 44 45 S_CROP(left / top = (5) - (1), width / height = (5') - (5)) 46 S_FMT(width / height = (6') - (6)) 47 48 Here: 49 50 (1) to (1') - whole max width or height 51 (1) to (2) - sensor cropped left or top 52 (2) to (2') - sensor cropped width or height 53 (3) to (3') - sensor scale 54 (3) to (4) - CEU cropped left or top 55 (4) to (4') - CEU cropped width or height 56 (5) to (5') - reverse sensor scale applied to CEU cropped width or height 57 (2) to (5) - reverse sensor scale applied to CEU cropped left or top 58 (6) to (6') - CEU scale - user window 59 60 61 S_FMT 62 ----- 63 64 Do not touch input rectangle - it is already optimal. 65 66 1. Calculate current sensor scales: 67 68 scale_s = ((2') - (2)) / ((3') - (3)) 69 70 2. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at 71 current sensor scales onto input window - this is user S_CROP: 72 73 width_u = (5') - (5) = ((4') - (4)) * scale_s 74 75 3. Calculate new combined scales from "effective" input window to requested user 76 window: 77 78 scale_comb = width_u / ((6') - (6)) 79 80 4. Calculate sensor output window by applying combined scales to real input 81 window: 82 83 width_s_out = ((7') - (7)) = ((2') - (2)) / scale_comb 84 85 5. Apply iterative sensor S_FMT for sensor output window. 86 87 subdev->video_ops->s_fmt(.width = width_s_out) 88 89 6. Retrieve sensor output window (g_fmt) 90 91 7. Calculate new sensor scales: 92 93 scale_s_new = ((3')_new - (3)_new) / ((2') - (2)) 94 95 8. Calculate new CEU crop - apply sensor scales to previously calculated 96 "effective" crop: 97 98 width_ceu = (4')_new - (4)_new = width_u / scale_s_new 99 left_ceu = (4)_new - (3)_new = ((5) - (2)) / scale_s_new 100 101 9. Use CEU cropping to crop to the new window: 102 103 ceu_crop(.width = width_ceu, .left = left_ceu) 104 105 10. Use CEU scaling to scale to the requested user window: 106 107 scale_ceu = width_ceu / width 108 109 110 S_CROP 111 ------ 112 113 The API at http://v4l2spec.bytesex.org/spec/x1904.htm says: 114 115 "...specification does not define an origin or units. However by convention 116 drivers should horizontally count unscaled samples relative to 0H." 117 118 We choose to follow the advise and interpret cropping units as client input 119 pixels. 120 121 Cropping is performed in the following 6 steps: 122 123 1. Request exactly user rectangle from the sensor. 124 125 2. If smaller - iterate until a larger one is obtained. Result: sensor cropped 126 to 2 : 2', target crop 5 : 5', current output format 6' - 6. 127 128 3. In the previous step the sensor has tried to preserve its output frame as 129 good as possible, but it could have changed. Retrieve it again. 130 131 4. Sensor scaled to 3 : 3'. Sensor's scale is (2' - 2) / (3' - 3). Calculate 132 intermediate window: 4' - 4 = (5' - 5) * (3' - 3) / (2' - 2) 133 134 5. Calculate and apply host scale = (6' - 6) / (4' - 4) 135 136 6. Calculate and apply host crop: 6 - 7 = (5 - 2) * (6' - 6) / (5' - 5) 137 138 -- 139 Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>