1*4882a593Smuzhiyun.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun.. _crop: 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun***************************************************** 6*4882a593SmuzhiyunImage Cropping, Insertion and Scaling -- the CROP API 7*4882a593Smuzhiyun***************************************************** 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun.. note:: 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun The CROP API is mostly superseded by the newer :ref:`SELECTION API 12*4882a593Smuzhiyun <selection-api>`. The new API should be preferred in most cases, 13*4882a593Smuzhiyun with the exception of pixel aspect ratio detection, which is 14*4882a593Smuzhiyun implemented by :ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>` and has no 15*4882a593Smuzhiyun equivalent in the SELECTION API. See :ref:`selection-vs-crop` for a 16*4882a593Smuzhiyun comparison of the two APIs. 17*4882a593Smuzhiyun 18*4882a593SmuzhiyunSome video capture devices can sample a subsection of the picture and 19*4882a593Smuzhiyunshrink or enlarge it to an image of arbitrary size. We call these 20*4882a593Smuzhiyunabilities cropping and scaling. Some video output devices can scale an 21*4882a593Smuzhiyunimage up or down and insert it at an arbitrary scan line and horizontal 22*4882a593Smuzhiyunoffset into a video signal. 23*4882a593Smuzhiyun 24*4882a593SmuzhiyunApplications can use the following API to select an area in the video 25*4882a593Smuzhiyunsignal, query the default area and the hardware limits. 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun.. note:: 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun Despite their name, the :ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>`, 30*4882a593Smuzhiyun :ref:`VIDIOC_G_CROP <VIDIOC_G_CROP>` and :ref:`VIDIOC_S_CROP 31*4882a593Smuzhiyun <VIDIOC_G_CROP>` ioctls apply to input as well as output devices. 32*4882a593Smuzhiyun 33*4882a593SmuzhiyunScaling requires a source and a target. On a video capture or overlay 34*4882a593Smuzhiyundevice the source is the video signal, and the cropping ioctls determine 35*4882a593Smuzhiyunthe area actually sampled. The target are images read by the application 36*4882a593Smuzhiyunor overlaid onto the graphics screen. Their size (and position for an 37*4882a593Smuzhiyunoverlay) is negotiated with the :ref:`VIDIOC_G_FMT <VIDIOC_G_FMT>` 38*4882a593Smuzhiyunand :ref:`VIDIOC_S_FMT <VIDIOC_G_FMT>` ioctls. 39*4882a593Smuzhiyun 40*4882a593SmuzhiyunOn a video output device the source are the images passed in by the 41*4882a593Smuzhiyunapplication, and their size is again negotiated with the 42*4882a593Smuzhiyun:ref:`VIDIOC_G_FMT <VIDIOC_G_FMT>` and :ref:`VIDIOC_S_FMT <VIDIOC_G_FMT>` 43*4882a593Smuzhiyunioctls, or may be encoded in a compressed video stream. The target is 44*4882a593Smuzhiyunthe video signal, and the cropping ioctls determine the area where the 45*4882a593Smuzhiyunimages are inserted. 46*4882a593Smuzhiyun 47*4882a593SmuzhiyunSource and target rectangles are defined even if the device does not 48*4882a593Smuzhiyunsupport scaling or the :ref:`VIDIOC_G_CROP <VIDIOC_G_CROP>` and 49*4882a593Smuzhiyun:ref:`VIDIOC_S_CROP <VIDIOC_G_CROP>` ioctls. Their size (and position 50*4882a593Smuzhiyunwhere applicable) will be fixed in this case. 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun.. note:: 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun All capture and output devices that support the CROP or SELECTION 55*4882a593Smuzhiyun API will also support the :ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>` 56*4882a593Smuzhiyun ioctl. 57*4882a593Smuzhiyun 58*4882a593SmuzhiyunCropping Structures 59*4882a593Smuzhiyun=================== 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun.. _crop-scale: 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun.. kernel-figure:: crop.svg 65*4882a593Smuzhiyun :alt: crop.svg 66*4882a593Smuzhiyun :align: center 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun Image Cropping, Insertion and Scaling 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun The cropping, insertion and scaling process 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun 74*4882a593SmuzhiyunFor capture devices the coordinates of the top left corner, width and 75*4882a593Smuzhiyunheight of the area which can be sampled is given by the ``bounds`` 76*4882a593Smuzhiyunsubstructure of the struct :c:type:`v4l2_cropcap` returned 77*4882a593Smuzhiyunby the :ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>` ioctl. To support a wide 78*4882a593Smuzhiyunrange of hardware this specification does not define an origin or units. 79*4882a593SmuzhiyunHowever by convention drivers should horizontally count unscaled samples 80*4882a593Smuzhiyunrelative to 0H (the leading edge of the horizontal sync pulse, see 81*4882a593Smuzhiyun:ref:`vbi-hsync`). Vertically ITU-R line numbers of the first field 82*4882a593Smuzhiyun(see ITU R-525 line numbering for :ref:`525 lines <vbi-525>` and for 83*4882a593Smuzhiyun:ref:`625 lines <vbi-625>`), multiplied by two if the driver 84*4882a593Smuzhiyuncan capture both fields. 85*4882a593Smuzhiyun 86*4882a593SmuzhiyunThe top left corner, width and height of the source rectangle, that is 87*4882a593Smuzhiyunthe area actually sampled, is given by struct 88*4882a593Smuzhiyun:c:type:`v4l2_crop` using the same coordinate system as 89*4882a593Smuzhiyunstruct :c:type:`v4l2_cropcap`. Applications can use the 90*4882a593Smuzhiyun:ref:`VIDIOC_G_CROP <VIDIOC_G_CROP>` and :ref:`VIDIOC_S_CROP <VIDIOC_G_CROP>` 91*4882a593Smuzhiyunioctls to get and set this rectangle. It must lie completely within the 92*4882a593Smuzhiyuncapture boundaries and the driver may further adjust the requested size 93*4882a593Smuzhiyunand/or position according to hardware limitations. 94*4882a593Smuzhiyun 95*4882a593SmuzhiyunEach capture device has a default source rectangle, given by the 96*4882a593Smuzhiyun``defrect`` substructure of struct 97*4882a593Smuzhiyun:c:type:`v4l2_cropcap`. The center of this rectangle 98*4882a593Smuzhiyunshall align with the center of the active picture area of the video 99*4882a593Smuzhiyunsignal, and cover what the driver writer considers the complete picture. 100*4882a593SmuzhiyunDrivers shall reset the source rectangle to the default when the driver 101*4882a593Smuzhiyunis first loaded, but not later. 102*4882a593Smuzhiyun 103*4882a593SmuzhiyunFor output devices these structures and ioctls are used accordingly, 104*4882a593Smuzhiyundefining the *target* rectangle where the images will be inserted into 105*4882a593Smuzhiyunthe video signal. 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun 108*4882a593SmuzhiyunScaling Adjustments 109*4882a593Smuzhiyun=================== 110*4882a593Smuzhiyun 111*4882a593SmuzhiyunVideo hardware can have various cropping, insertion and scaling 112*4882a593Smuzhiyunlimitations. It may only scale up or down, support only discrete scaling 113*4882a593Smuzhiyunfactors, or have different scaling abilities in horizontal and vertical 114*4882a593Smuzhiyundirection. Also it may not support scaling at all. At the same time the 115*4882a593Smuzhiyunstruct :c:type:`v4l2_crop` rectangle may have to be aligned, 116*4882a593Smuzhiyunand both the source and target rectangles may have arbitrary upper and 117*4882a593Smuzhiyunlower size limits. In particular the maximum ``width`` and ``height`` in 118*4882a593Smuzhiyunstruct :c:type:`v4l2_crop` may be smaller than the struct 119*4882a593Smuzhiyun:c:type:`v4l2_cropcap`. ``bounds`` area. Therefore, as 120*4882a593Smuzhiyunusual, drivers are expected to adjust the requested parameters and 121*4882a593Smuzhiyunreturn the actual values selected. 122*4882a593Smuzhiyun 123*4882a593SmuzhiyunApplications can change the source or the target rectangle first, as 124*4882a593Smuzhiyunthey may prefer a particular image size or a certain area in the video 125*4882a593Smuzhiyunsignal. If the driver has to adjust both to satisfy hardware 126*4882a593Smuzhiyunlimitations, the last requested rectangle shall take priority, and the 127*4882a593Smuzhiyundriver should preferably adjust the opposite one. The 128*4882a593Smuzhiyun:ref:`VIDIOC_TRY_FMT <VIDIOC_G_FMT>` ioctl however shall not change 129*4882a593Smuzhiyunthe driver state and therefore only adjust the requested rectangle. 130*4882a593Smuzhiyun 131*4882a593SmuzhiyunSuppose scaling on a video capture device is restricted to a factor 1:1 132*4882a593Smuzhiyunor 2:1 in either direction and the target image size must be a multiple 133*4882a593Smuzhiyunof 16 × 16 pixels. The source cropping rectangle is set to defaults, 134*4882a593Smuzhiyunwhich are also the upper limit in this example, of 640 × 400 pixels at 135*4882a593Smuzhiyunoffset 0, 0. An application requests an image size of 300 × 225 pixels, 136*4882a593Smuzhiyunassuming video will be scaled down from the "full picture" accordingly. 137*4882a593SmuzhiyunThe driver sets the image size to the closest possible values 304 × 224, 138*4882a593Smuzhiyunthen chooses the cropping rectangle closest to the requested size, that 139*4882a593Smuzhiyunis 608 × 224 (224 × 2:1 would exceed the limit 400). The offset 0, 0 is 140*4882a593Smuzhiyunstill valid, thus unmodified. Given the default cropping rectangle 141*4882a593Smuzhiyunreported by :ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>` the application can 142*4882a593Smuzhiyuneasily propose another offset to center the cropping rectangle. 143*4882a593Smuzhiyun 144*4882a593SmuzhiyunNow the application may insist on covering an area using a picture 145*4882a593Smuzhiyunaspect ratio closer to the original request, so it asks for a cropping 146*4882a593Smuzhiyunrectangle of 608 × 456 pixels. The present scaling factors limit 147*4882a593Smuzhiyuncropping to 640 × 384, so the driver returns the cropping size 608 × 384 148*4882a593Smuzhiyunand adjusts the image size to closest possible 304 × 192. 149*4882a593Smuzhiyun 150*4882a593Smuzhiyun 151*4882a593SmuzhiyunExamples 152*4882a593Smuzhiyun======== 153*4882a593Smuzhiyun 154*4882a593SmuzhiyunSource and target rectangles shall remain unchanged across closing and 155*4882a593Smuzhiyunreopening a device, such that piping data into or out of a device will 156*4882a593Smuzhiyunwork without special preparations. More advanced applications should 157*4882a593Smuzhiyunensure the parameters are suitable before starting I/O. 158*4882a593Smuzhiyun 159*4882a593Smuzhiyun.. note:: 160*4882a593Smuzhiyun 161*4882a593Smuzhiyun On the next two examples, a video capture device is assumed; 162*4882a593Smuzhiyun change ``V4L2_BUF_TYPE_VIDEO_CAPTURE`` for other types of device. 163*4882a593Smuzhiyun 164*4882a593SmuzhiyunExample: Resetting the cropping parameters 165*4882a593Smuzhiyun========================================== 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun.. code-block:: c 168*4882a593Smuzhiyun 169*4882a593Smuzhiyun struct v4l2_cropcap cropcap; 170*4882a593Smuzhiyun struct v4l2_crop crop; 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun memset (&cropcap, 0, sizeof (cropcap)); 173*4882a593Smuzhiyun cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 174*4882a593Smuzhiyun 175*4882a593Smuzhiyun if (-1 == ioctl (fd, VIDIOC_CROPCAP, &cropcap)) { 176*4882a593Smuzhiyun perror ("VIDIOC_CROPCAP"); 177*4882a593Smuzhiyun exit (EXIT_FAILURE); 178*4882a593Smuzhiyun } 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun memset (&crop, 0, sizeof (crop)); 181*4882a593Smuzhiyun crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 182*4882a593Smuzhiyun crop.c = cropcap.defrect; 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun /* Ignore if cropping is not supported (EINVAL). */ 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun if (-1 == ioctl (fd, VIDIOC_S_CROP, &crop) 187*4882a593Smuzhiyun && errno != EINVAL) { 188*4882a593Smuzhiyun perror ("VIDIOC_S_CROP"); 189*4882a593Smuzhiyun exit (EXIT_FAILURE); 190*4882a593Smuzhiyun } 191*4882a593Smuzhiyun 192*4882a593Smuzhiyun 193*4882a593SmuzhiyunExample: Simple downscaling 194*4882a593Smuzhiyun=========================== 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun.. code-block:: c 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun struct v4l2_cropcap cropcap; 199*4882a593Smuzhiyun struct v4l2_format format; 200*4882a593Smuzhiyun 201*4882a593Smuzhiyun reset_cropping_parameters (); 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun /* Scale down to 1/4 size of full picture. */ 204*4882a593Smuzhiyun 205*4882a593Smuzhiyun memset (&format, 0, sizeof (format)); /* defaults */ 206*4882a593Smuzhiyun 207*4882a593Smuzhiyun format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 208*4882a593Smuzhiyun 209*4882a593Smuzhiyun format.fmt.pix.width = cropcap.defrect.width >> 1; 210*4882a593Smuzhiyun format.fmt.pix.height = cropcap.defrect.height >> 1; 211*4882a593Smuzhiyun format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; 212*4882a593Smuzhiyun 213*4882a593Smuzhiyun if (-1 == ioctl (fd, VIDIOC_S_FMT, &format)) { 214*4882a593Smuzhiyun perror ("VIDIOC_S_FORMAT"); 215*4882a593Smuzhiyun exit (EXIT_FAILURE); 216*4882a593Smuzhiyun } 217*4882a593Smuzhiyun 218*4882a593Smuzhiyun /* We could check the actual image size now, the actual scaling factor 219*4882a593Smuzhiyun or if the driver can scale at all. */ 220*4882a593Smuzhiyun 221*4882a593SmuzhiyunExample: Selecting an output area 222*4882a593Smuzhiyun================================= 223*4882a593Smuzhiyun 224*4882a593Smuzhiyun.. note:: This example assumes an output device. 225*4882a593Smuzhiyun 226*4882a593Smuzhiyun.. code-block:: c 227*4882a593Smuzhiyun 228*4882a593Smuzhiyun struct v4l2_cropcap cropcap; 229*4882a593Smuzhiyun struct v4l2_crop crop; 230*4882a593Smuzhiyun 231*4882a593Smuzhiyun memset (&cropcap, 0, sizeof (cropcap)); 232*4882a593Smuzhiyun cropcap.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 233*4882a593Smuzhiyun 234*4882a593Smuzhiyun if (-1 == ioctl (fd, VIDIOC_CROPCAP;, &cropcap)) { 235*4882a593Smuzhiyun perror ("VIDIOC_CROPCAP"); 236*4882a593Smuzhiyun exit (EXIT_FAILURE); 237*4882a593Smuzhiyun } 238*4882a593Smuzhiyun 239*4882a593Smuzhiyun memset (&crop, 0, sizeof (crop)); 240*4882a593Smuzhiyun 241*4882a593Smuzhiyun crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 242*4882a593Smuzhiyun crop.c = cropcap.defrect; 243*4882a593Smuzhiyun 244*4882a593Smuzhiyun /* Scale the width and height to 50 % of their original size 245*4882a593Smuzhiyun and center the output. */ 246*4882a593Smuzhiyun 247*4882a593Smuzhiyun crop.c.width /= 2; 248*4882a593Smuzhiyun crop.c.height /= 2; 249*4882a593Smuzhiyun crop.c.left += crop.c.width / 2; 250*4882a593Smuzhiyun crop.c.top += crop.c.height / 2; 251*4882a593Smuzhiyun 252*4882a593Smuzhiyun /* Ignore if cropping is not supported (EINVAL). */ 253*4882a593Smuzhiyun 254*4882a593Smuzhiyun if (-1 == ioctl (fd, VIDIOC_S_CROP, &crop) 255*4882a593Smuzhiyun && errno != EINVAL) { 256*4882a593Smuzhiyun perror ("VIDIOC_S_CROP"); 257*4882a593Smuzhiyun exit (EXIT_FAILURE); 258*4882a593Smuzhiyun } 259*4882a593Smuzhiyun 260*4882a593SmuzhiyunExample: Current scaling factor and pixel aspect 261*4882a593Smuzhiyun================================================ 262*4882a593Smuzhiyun 263*4882a593Smuzhiyun.. note:: This example assumes a video capture device. 264*4882a593Smuzhiyun 265*4882a593Smuzhiyun.. code-block:: c 266*4882a593Smuzhiyun 267*4882a593Smuzhiyun struct v4l2_cropcap cropcap; 268*4882a593Smuzhiyun struct v4l2_crop crop; 269*4882a593Smuzhiyun struct v4l2_format format; 270*4882a593Smuzhiyun double hscale, vscale; 271*4882a593Smuzhiyun double aspect; 272*4882a593Smuzhiyun int dwidth, dheight; 273*4882a593Smuzhiyun 274*4882a593Smuzhiyun memset (&cropcap, 0, sizeof (cropcap)); 275*4882a593Smuzhiyun cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 276*4882a593Smuzhiyun 277*4882a593Smuzhiyun if (-1 == ioctl (fd, VIDIOC_CROPCAP, &cropcap)) { 278*4882a593Smuzhiyun perror ("VIDIOC_CROPCAP"); 279*4882a593Smuzhiyun exit (EXIT_FAILURE); 280*4882a593Smuzhiyun } 281*4882a593Smuzhiyun 282*4882a593Smuzhiyun memset (&crop, 0, sizeof (crop)); 283*4882a593Smuzhiyun crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 284*4882a593Smuzhiyun 285*4882a593Smuzhiyun if (-1 == ioctl (fd, VIDIOC_G_CROP, &crop)) { 286*4882a593Smuzhiyun if (errno != EINVAL) { 287*4882a593Smuzhiyun perror ("VIDIOC_G_CROP"); 288*4882a593Smuzhiyun exit (EXIT_FAILURE); 289*4882a593Smuzhiyun } 290*4882a593Smuzhiyun 291*4882a593Smuzhiyun /* Cropping not supported. */ 292*4882a593Smuzhiyun crop.c = cropcap.defrect; 293*4882a593Smuzhiyun } 294*4882a593Smuzhiyun 295*4882a593Smuzhiyun memset (&format, 0, sizeof (format)); 296*4882a593Smuzhiyun format.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 297*4882a593Smuzhiyun 298*4882a593Smuzhiyun if (-1 == ioctl (fd, VIDIOC_G_FMT, &format)) { 299*4882a593Smuzhiyun perror ("VIDIOC_G_FMT"); 300*4882a593Smuzhiyun exit (EXIT_FAILURE); 301*4882a593Smuzhiyun } 302*4882a593Smuzhiyun 303*4882a593Smuzhiyun /* The scaling applied by the driver. */ 304*4882a593Smuzhiyun 305*4882a593Smuzhiyun hscale = format.fmt.pix.width / (double) crop.c.width; 306*4882a593Smuzhiyun vscale = format.fmt.pix.height / (double) crop.c.height; 307*4882a593Smuzhiyun 308*4882a593Smuzhiyun aspect = cropcap.pixelaspect.numerator / 309*4882a593Smuzhiyun (double) cropcap.pixelaspect.denominator; 310*4882a593Smuzhiyun aspect = aspect * hscale / vscale; 311*4882a593Smuzhiyun 312*4882a593Smuzhiyun /* Devices following ITU-R BT.601 do not capture 313*4882a593Smuzhiyun square pixels. For playback on a computer monitor 314*4882a593Smuzhiyun we should scale the images to this size. */ 315*4882a593Smuzhiyun 316*4882a593Smuzhiyun dwidth = format.fmt.pix.width / aspect; 317*4882a593Smuzhiyun dheight = format.fmt.pix.height; 318