Back to home page

OSCL-LXR

 
 

    


0001 .. SPDX-License-Identifier: GPL-2.0
0002 
0003 Cropping and Scaling algorithm, used in the sh_mobile_ceu_camera driver
0004 =======================================================================
0005 
0006 Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
0007 
0008 Terminology
0009 -----------
0010 
0011 sensor scales: horizontal and vertical scales, configured by the sensor driver
0012 host scales: -"- host driver
0013 combined scales: sensor_scale * host_scale
0014 
0015 
0016 Generic scaling / cropping scheme
0017 ---------------------------------
0018 
0019 .. code-block:: none
0020 
0021         -1--
0022         |
0023         -2-- -\
0024         |      --\
0025         |         --\
0026         +-5-- .      -- -3-- -\
0027         |      `...            -\
0028         |          `... -4-- .   - -7..
0029         |                     `.
0030         |                       `. .6--
0031         |
0032         |                        . .6'-
0033         |                      .´
0034         |           ... -4'- .´
0035         |       ...´             - -7'.
0036         +-5'- .´               -/
0037         |            -- -3'- -/
0038         |         --/
0039         |      --/
0040         -2'- -/
0041         |
0042         |
0043         -1'-
0044 
0045 In the above chart minuses and slashes represent "real" data amounts, points and
0046 accents represent "useful" data, basically, CEU scaled and cropped output,
0047 mapped back onto the client's source plane.
0048 
0049 Such a configuration can be produced by user requests:
0050 
0051 S_CROP(left / top = (5) - (1), width / height = (5') - (5))
0052 S_FMT(width / height = (6') - (6))
0053 
0054 Here:
0055 
0056 (1) to (1') - whole max width or height
0057 (1) to (2)  - sensor cropped left or top
0058 (2) to (2') - sensor cropped width or height
0059 (3) to (3') - sensor scale
0060 (3) to (4)  - CEU cropped left or top
0061 (4) to (4') - CEU cropped width or height
0062 (5) to (5') - reverse sensor scale applied to CEU cropped width or height
0063 (2) to (5)  - reverse sensor scale applied to CEU cropped left or top
0064 (6) to (6') - CEU scale - user window
0065 
0066 
0067 S_FMT
0068 -----
0069 
0070 Do not touch input rectangle - it is already optimal.
0071 
0072 1. Calculate current sensor scales:
0073 
0074         scale_s = ((2') - (2)) / ((3') - (3))
0075 
0076 2. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at
0077 current sensor scales onto input window - this is user S_CROP:
0078 
0079         width_u = (5') - (5) = ((4') - (4)) * scale_s
0080 
0081 3. Calculate new combined scales from "effective" input window to requested user
0082 window:
0083 
0084         scale_comb = width_u / ((6') - (6))
0085 
0086 4. Calculate sensor output window by applying combined scales to real input
0087 window:
0088 
0089         width_s_out = ((7') - (7)) = ((2') - (2)) / scale_comb
0090 
0091 5. Apply iterative sensor S_FMT for sensor output window.
0092 
0093         subdev->video_ops->s_fmt(.width = width_s_out)
0094 
0095 6. Retrieve sensor output window (g_fmt)
0096 
0097 7. Calculate new sensor scales:
0098 
0099         scale_s_new = ((3')_new - (3)_new) / ((2') - (2))
0100 
0101 8. Calculate new CEU crop - apply sensor scales to previously calculated
0102 "effective" crop:
0103 
0104         width_ceu = (4')_new - (4)_new = width_u / scale_s_new
0105         left_ceu = (4)_new - (3)_new = ((5) - (2)) / scale_s_new
0106 
0107 9. Use CEU cropping to crop to the new window:
0108 
0109         ceu_crop(.width = width_ceu, .left = left_ceu)
0110 
0111 10. Use CEU scaling to scale to the requested user window:
0112 
0113         scale_ceu = width_ceu / width
0114 
0115 
0116 S_CROP
0117 ------
0118 
0119 The :ref:`V4L2 crop API <crop-scale>` says:
0120 
0121 "...specification does not define an origin or units. However by convention
0122 drivers should horizontally count unscaled samples relative to 0H."
0123 
0124 We choose to follow the advise and interpret cropping units as client input
0125 pixels.
0126 
0127 Cropping is performed in the following 6 steps:
0128 
0129 1. Request exactly user rectangle from the sensor.
0130 
0131 2. If smaller - iterate until a larger one is obtained. Result: sensor cropped
0132    to 2 : 2', target crop 5 : 5', current output format 6' - 6.
0133 
0134 3. In the previous step the sensor has tried to preserve its output frame as
0135    good as possible, but it could have changed. Retrieve it again.
0136 
0137 4. Sensor scaled to 3 : 3'. Sensor's scale is (2' - 2) / (3' - 3). Calculate
0138    intermediate window: 4' - 4 = (5' - 5) * (3' - 3) / (2' - 2)
0139 
0140 5. Calculate and apply host scale = (6' - 6) / (4' - 4)
0141 
0142 6. Calculate and apply host crop: 6 - 7 = (5 - 2) * (6' - 6) / (5' - 5)