Hi All,

About 3 months ago I sent an email to the v4l mailing list asking some questions about implementing CROP support to the saa7115 driver. By that I mean the ability to crop off the edges of your input video while still on the card instead of doing it in software (I use it to crop off some black bars that my external sat reciever adds). Hans was nice enough to give me some pointers and I half way implemented this before getting distracted by other projects and shelving it. I thought I'd dust off what I have and send it to the list to see if I can get some help finishing it up. Probably, I should send the saa7115.c portions to the v4l list to get some feedback as well?

The attached patches are based on kernel 2.6.16 and ivtv-0.6.2. I've had no luck in getting SNV ivtv or mercurial v4l-dvb to compile on my Fedora Core 5 system. What the attached patches do are add the V4L2 CROP ioctl() to the saa7115 driver and ivtv driver. I've also added two new options to ivtvctl that map to the V4L2 API: --get-crop and --set-crop.

What doesn't work right now:

1) Specifying crop height values that are close to the FMT capture height doesn't work. When the video scale ratio (output/input) approaches 1 then the captured video only gets a few lines towards the top. For example, if your input video is cropped to 720x470 and your capturing FMT is set to 720x480 then only about 10 lines of picture get updated every frame. If you crop your input window to 720x480 and capture a video of 720x600 then it works fine (480/470 is to close to one, 600/480 isn't so bad).

2) I've noticed a few combinations of widths that cause the color to switch to shades of blue. Theres probably some limitation I don't understand yet (for instance, maybe scale widths have to be divisible by 4).

3) Setting the cropping to very low values causes the driver to lock up or stall. For example, if I set the input crop size to a width of 100 (out of 720 possible width) then the call to ivtvctl locks up and I can't read data from /dev/video0. The saa7715 docs mention some limits on scaling but I haven't calculated those yet to see what is to low. Sometimes this even locks up the whole computer.

Thanks for any help,
Chris

*** saa7115.c.orig	2006-06-04 16:14:09.000000000 -0500
--- saa7115.c	2006-06-04 15:18:23.000000000 -0500
***************
*** 209,215 ****
  	0xc7, 0x02,		/* hsize hi (input) */
  	0xc8, 0x12,		/* voffset low (input), 0x12 = 18 */
  	0xc9, 0x00,		/* voffset hi (input) */
! 	0xca, 0xf8,		/* vsize low (input), 0xf8 = 248 */
  	0xcb, 0x00,		/* vsize hi (input) */
  	0xcc, 0xd0,		/* hsize low (output), 0x02d0 = 720 */
  	0xcd, 0x02,		/* hsize hi (output) */
--- 209,215 ----
          0xc7, 0x02,             /* hsize hi (input) */
          0xc8, 0x12,             /* voffset low (input), 0x12 = 18 */
          0xc9, 0x00,             /* voffset hi (input) */
!         0xca, 0xf0,             /* vsize low (input), 0xf0 = 240 */
          0xcb, 0x00,             /* vsize hi (input) */
          0xcc, 0xd0,             /* hsize low (output), 0x02d0 = 720 */
          0xcd, 0x02,             /* hsize hi (output) */
***************
*** 848,858 ****
  
  static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
  {
- 	struct saa7115_state *state = i2c_get_clientdata(client);
  	struct v4l2_pix_format *pix;
! 	int HPSC, HFSC;
  	int VSCY, Vsrc;
- 	int is_50hz = state->std & V4L2_STD_625_50;
  
  	if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
  		saa7115_set_lcr(client, &fmt->fmt.sliced);
--- 848,856 ----
  
  static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
  {
          struct v4l2_pix_format *pix;
!         int HPSC, HFSC, Hsrc;
          int VSCY, Vsrc;
  
          if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
                  saa7115_set_lcr(client, &fmt->fmt.sliced);
***************
*** 880,895 ****
  	saa7115_write(client, 0xce, (u8) (pix->height & 0xff));
  	saa7115_write(client, 0xcf, (u8) ((pix->height >> 8) & 0xff));
  
  	/* Scaling settings */
  	/* Hprescaler is floor(inres/outres) */
! 	/* FIXME hardcoding input res */
! 	if (pix->width != 720) {
! 		HPSC = (int)(720 / pix->width);
  		/* 0 is not allowed (div. by zero) */
  		HPSC = HPSC ? HPSC : 1;
! 		HFSC = (int)((1024 * 720) / (HPSC * pix->width));
  
! 		v4l_dbg(1, debug, client, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
  		/* FIXME hardcodes to "Task B"
  		 * write H prescaler integer */
  		saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f));
--- 878,894 ----
          saa7115_write(client, 0xce, (u8) (pix->height & 0xff));
          saa7115_write(client, 0xcf, (u8) ((pix->height >> 8) & 0xff));
  
+         Hsrc = saa7115_read(client, 0xc6);
+         Hsrc |= ((saa7115_read(client, 0xc7) & 0x0f) << 8);
+ 
          /* Scaling settings */
          /* Hprescaler is floor(inres/outres) */
!         HPSC = (int)(Hsrc / pix->width);
          /* 0 is not allowed (div. by zero) */
          HPSC = HPSC ? HPSC : 1;
!         HFSC = (int)((1024 * Hsrc) / (HPSC * pix->width));
  
!         v4l_dbg(1, debug, client, "Hsrc: %d Hpsc: 0x%05x, Hfsc: 0x%05x\n", Hsrc, HPSC, HFSC);
          /* FIXME hardcodes to "Task B"
           * write H prescaler integer */
          saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f));
***************
*** 901,919 ****
  		 * must be lum/2, so i'll just bitshift :) */
  		saa7115_write(client, 0xDC, (u8) ((HFSC >> 1) & 0xff));
  		saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff));
- 	} else {
- 		if (is_50hz) {
- 			v4l_dbg(1, debug, client, "Setting full 50hz width\n");
- 			saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x);
- 		} else {
- 			v4l_dbg(1, debug, client, "Setting full 60hz width\n");
- 			saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
- 		}
- 	}
  
! 	Vsrc = is_50hz ? 576 : 480;
  
- 	if (pix->height != Vsrc) {
  		VSCY = (int)((1024 * Vsrc) / pix->height);
  		v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
  
--- 900,911 ----
           * must be lum/2, so i'll just bitshift :) */
          saa7115_write(client, 0xDC, (u8) ((HFSC >> 1) & 0xff));
          saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff));
  
!         Vsrc = saa7115_read(client, 0xca);
!         Vsrc |= ((saa7115_read(client, 0xcb) &0x0f) << 8);
!         /* Account for interlacing */
!         Vsrc *= 2;
  
          VSCY = (int)((1024 * Vsrc) / pix->height);
          v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
  
***************
*** 927,946 ****
  		/* write V fine-scaling (chrominance) */
  		saa7115_write(client, 0xe2, (u8) (VSCY & 0xff));
  		saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff));
! 	} else {
  		if (is_50hz) {
! 			v4l_dbg(1, debug, client, "Setting full 50Hz height\n");
! 			saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y);
  		} else {
! 			v4l_dbg(1, debug, client, "Setting full 60hz height\n");
! 			saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
  		}
  	}
  
  	saa7115_writeregs(client, saa7115_cfg_reset_scaler);
  	return 0;
  }
  
  /* Decode the sliced VBI data stream as created by the saa7115.
     The format is described in the saa7115 datasheet in Tables 25 and 26
     and in Figure 33.
--- 919,1024 ----
          /* write V fine-scaling (chrominance) */
          saa7115_write(client, 0xe2, (u8) (VSCY & 0xff));
          saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff));
! 
!         saa7115_writeregs(client, saa7115_cfg_reset_scaler);
!         return 0;
! }
! 
! static int saa7115_set_v4lcrop(struct i2c_client *client, 
!                                struct v4l2_crop *crop)
! {
!         struct saa7115_state *state = i2c_get_clientdata(client);
!         int HPSC, HFSC, Hdest, Hoffset;
!         int VSCY, Vdest, Voffset;
!         int is_50hz = state->std & V4L2_STD_625_50;
! 
!         if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
!                 return -EINVAL;
! 
!         v4l_dbg(1, debug, client, "decoder set crop\n");
! 
!         /* FIXME need better bounds checking here */
!         if ((crop->c.width < 1) || crop->c.left < 0 ||
!             (crop->c.width + crop->c.left > 720))
!                 return -EINVAL;
          if (is_50hz) {
!             if ((crop->c.height < 1) || crop->c.top < 0 ||
!                 (crop->c.height + crop->c.height > 576))
!                 return -EINVAL;
          } else {
!             if ((crop->c.height < 1) || crop->c.top < 0 ||
!                 (crop->c.height + crop->c.top > 480))
!                 return -EINVAL;
          }
+  
+         /* probably have a valid size, let's set it */
+         /* Set input left/top/width/height */
+         /* left */
+         /* minimum offset is 2 */
+         Hoffset = 2+crop->c.left;
+         saa7115_write(client, 0xc4, (u8) (Hoffset & 0xff));
+         saa7115_write(client, 0xc5, (u8) (((Hoffset) >> 8) & 0x0f));
+         /* top */
+         if (is_50hz) {
+             Voffset = 22 + crop->c.top;
+         } else {
+             Voffset = 18 + crop->c.top;
          }
+         saa7115_write(client, 0xc8, (u8) (Voffset & 0xff));
+         saa7115_write(client, 0xc9, (u8) ((Voffset >> 8) & 0x0f));
+         /* width */
+         saa7115_write(client, 0xc6, (u8) (crop->c.width & 0xff));
+         saa7115_write(client, 0xc7, (u8) ((crop->c.width >> 8) & 0x0f));
+         /* height */
+         saa7115_write(client, 0xca, (u8) ((crop->c.height / 2) & 0xff));
+         saa7115_write(client, 0xcb, (u8) (((crop->c.height / 2) >> 8) & 0x0f));
+ 
+         Hdest = saa7115_read(client, 0xcc);
+         Hdest |= ((saa7115_read(client, 0xcd) & 0x0f) << 8);
+ 
+         /* Scaling settings */
+         /* Hprescaler is floor(inres/outres) */
+         HPSC = (int)(crop->c.width / Hdest);
+         /* 0 is not allowed (div. by zero) */
+         HPSC = HPSC ? HPSC : 1;
+         HFSC = (int)((1024 * crop->c.width) / (HPSC * Hdest));
+ 
+         v4l_dbg(1, debug, client, "Hdest: %d Hpsc: 0x%05x, Hfsc: 0x%05x\n", Hdest, HPSC, HFSC);
+         /* FIXME hardcodes to "Task B"
+          * write H prescaler integer */
+         saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f));
+ 
+         /* write H fine-scaling (luminance) */
+         saa7115_write(client, 0xd8, (u8) (HFSC & 0xff));
+         saa7115_write(client, 0xd9, (u8) ((HFSC >> 8) & 0xff));
+         /* write H fine-scaling (chrominance)
+          * must be lum/2, so i'll just bitshift :) */
+         saa7115_write(client, 0xDC, (u8) ((HFSC >> 1) & 0xff));
+         saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff));
+ 
+         Vdest = saa7115_read(client, 0xce);
+         Vdest |= ((saa7115_read(client, 0xcf) &0x0f) << 8);
+         /* Account for interlacing */
+ 
+         VSCY = (int)((1024 * crop->c.height) / Vdest);
+         v4l_dbg(1, debug, client, "Vdest: %d, Vscy: 0x%05x\n", Vdest, VSCY);
+ 
+         /* Correct Contrast and Luminance */
+         saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY));
+         saa7115_write(client, 0xd6, (u8) (64 * 1024 / VSCY));
+ 
+         /* write V fine-scaling (luminance) */
+         saa7115_write(client, 0xe0, (u8) (VSCY & 0xff));
+         saa7115_write(client, 0xe1, (u8) ((VSCY >> 8) & 0xff));
+         /* write V fine-scaling (chrominance) */
+         saa7115_write(client, 0xe2, (u8) (VSCY & 0xff));
+         saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff));
  
          saa7115_writeregs(client, saa7115_cfg_reset_scaler);
          return 0;
  }
  
+ 
  /* Decode the sliced VBI data stream as created by the saa7115.
     The format is described in the saa7115 datasheet in Tables 25 and 26
     and in Figure 33.
***************
*** 1067,1072 ****
--- 1145,1153 ----
          case VIDIOC_G_FMT:
                  return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg);
  
+         case VIDIOC_S_CROP:
+                 return saa7115_set_v4lcrop(client, (struct v4l2_crop *)arg);
+ 
          case VIDIOC_INT_AUDIO_CLOCK_FREQ:
                  return saa7115_set_audio_clock_freq(client, *(u32 *)arg);
  
Only in ivtv-0.6.2.crop/driver: ivtv-audio.o
Only in ivtv-0.6.2.crop/driver: .ivtv-audio.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-cards.o
Only in ivtv-0.6.2.crop/driver: .ivtv-cards.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-controls.o
Only in ivtv-0.6.2.crop/driver: .ivtv-controls.o.cmd
diff -wpr ivtv-0.6.2/driver/ivtv-driver.h ivtv-0.6.2.crop/driver/ivtv-driver.h
*** ivtv-0.6.2/driver/ivtv-driver.h	2006-04-29 11:48:37.000000000 -0500
--- ivtv-0.6.2.crop/driver/ivtv-driver.h	2006-06-03 16:49:35.000000000 -0500
*************** struct ivtv {
*** 998,1003 ****
--- 998,1004 ----
          v4l2_std_id std;
          v4l2_std_id tuner_std;  /* The norm of the tuner (fixed) */
          u32 width, height;
+         u32 crop_left, crop_top, crop_width, crop_height;
          u32 vbi_start[2], vbi_count;
          int streamcount;        /* Number of elements in streams */
          struct ivtv_stream *streams;
Only in ivtv-0.6.2.crop/driver: ivtv-driver.h~
Only in ivtv-0.6.2.crop/driver: ivtv-driver.o
Only in ivtv-0.6.2.crop/driver: .ivtv-driver.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-fb.ko
Only in ivtv-0.6.2.crop/driver: .ivtv-fb.ko.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-fb.mod.c
Only in ivtv-0.6.2.crop/driver: ivtv-fb.mod.o
Only in ivtv-0.6.2.crop/driver: .ivtv-fb.mod.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-fb.o
Only in ivtv-0.6.2.crop/driver: .ivtv-fb.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-fileops.o
Only in ivtv-0.6.2.crop/driver: .ivtv-fileops.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-firmware.o
Only in ivtv-0.6.2.crop/driver: .ivtv-firmware.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-gpio.o
Only in ivtv-0.6.2.crop/driver: .ivtv-gpio.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-i2c.o
Only in ivtv-0.6.2.crop/driver: .ivtv-i2c.o.cmd
diff -wpr ivtv-0.6.2/driver/ivtv-ioctl.c ivtv-0.6.2.crop/driver/ivtv-ioctl.c
*** ivtv-0.6.2/driver/ivtv-ioctl.c	2006-04-19 16:37:13.000000000 -0500
--- ivtv-0.6.2.crop/driver/ivtv-ioctl.c	2006-06-04 16:25:15.000000000 -0500
*************** static int ivtv_try_or_set_fmt(struct iv
*** 565,570 ****
--- 565,624 ----
          return 0;
  }
  
+ static int ivtv_get_crop(struct ivtv *itv, int streamtype, 
+                          struct v4l2_crop *crop)
+ {
+         switch (crop->type) {
+         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                 crop->c.left = itv->crop_left;
+                 crop->c.top = itv->crop_top;
+                 crop->c.width = itv->crop_width;
+                 crop->c.height = itv->crop_height;
+                 break;
+ 
+         default:
+                 return -EINVAL;
+         }
+         return 0;
+ }
+ 
+ static int ivtv_set_crop(struct ivtv *itv, int streamtype,
+                          struct v4l2_crop *crop)
+ {
+         int rc;
+ 
+         // set crop size
+         if (crop->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+                 struct v4l2_crop c;
+ 
+                 if ((itv->crop_left != crop->c.left ||
+                      itv->crop_top != crop->c.top ||
+                      itv->crop_width != crop->c.width ||
+                      itv->crop_height != crop->c.height) &&
+                     atomic_read(&itv->capturing) > 0) {
+                         return -EBUSY;
+                 }
+ 
+                 c.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                 c.c.left = crop->c.left;
+                 c.c.top = crop->c.top;
+                 c.c.width = crop->c.width;
+                 c.c.height = crop->c.height;
+ 
+                 rc = itv->video_dec_func(itv, VIDIOC_S_CROP, &c);
+                 if (rc != 0)
+                     return rc;
+ 
+                 itv->crop_left = c.c.left;
+                 itv->crop_top = c.c.top;
+                 itv->crop_width = c.c.width;
+                 itv->crop_height = c.c.height;
+ 
+                 return ivtv_get_crop(itv, streamtype, crop);
+         }
+ 
+         return -EINVAL;
+ }
  
  static int ivtv_internal_ioctls(struct ivtv *itv, int streamtype, unsigned int cmd,
                           void *arg)
*************** int ivtv_v4l2_ioctls(struct ivtv *itv, s
*** 833,838 ****
--- 887,909 ----
                  return ivtv_get_fmt(itv, streamtype, fmt);
          }
  
+         case VIDIOC_S_CROP: {
+                 struct v4l2_crop *crop = arg;
+ 
+                 IVTV_DEBUG_IOCTL("VIDIOC_S_CROP\n");
+                 return ivtv_set_crop(itv, streamtype, crop);
+         }
+ 
+         case VIDIOC_G_CROP: {
+                 struct v4l2_crop *crop = arg;
+                 int type = crop->type;
+ 
+                 IVTV_DEBUG_IOCTL("VIDIOC_G_CROP\n");
+                 memset(crop, 0, sizeof(*crop));
+                 crop->type = type;
+                 return ivtv_get_crop(itv, streamtype, crop);
+         }
+ 
          case VIDIOC_G_INPUT:{
                  IVTV_DEBUG_IOCTL("VIDIOC_G_INPUT\n");
  
*************** int ivtv_v4l2_ioctls(struct ivtv *itv, s
*** 984,993 ****
--- 1055,1067 ----
  
                  itv->std = std;
                  itv->width = 720;
+                 itv->crop_width=720;
+                 itv->crop_left = itv->crop_top = 0;
                  if (itv->std & V4L2_STD_525_60) {
                          itv->is_50hz = 0;
                          itv->is_60hz = 1;
                          itv->height = 480;
+                         itv->crop_height = 480;
                          itv->vbi_count = 12;
                          itv->vbi_start[0] = 10;
                          itv->vbi_start[1] = 273;
*************** int ivtv_v4l2_ioctls(struct ivtv *itv, s
*** 995,1000 ****
--- 1069,1075 ----
                          itv->is_50hz = 1;
                          itv->is_60hz = 0;
                          itv->height = 576;
+                         itv->crop_height = 576;
                          itv->vbi_count = 18;
                          itv->vbi_start[0] = 6;
                          itv->vbi_start[1] = 318;
*************** static int ivtv_v4l2_do_ioctl(struct ino
*** 1678,1683 ****
--- 1753,1760 ----
          case VIDIOC_G_FMT:
          case VIDIOC_S_FMT:
          case VIDIOC_TRY_FMT:
+         case VIDIOC_G_CROP:
+         case VIDIOC_S_CROP:
          case VIDIOC_G_FREQUENCY:
          case VIDIOC_S_FREQUENCY:
          case VIDIOC_ENUMSTD:
Only in ivtv-0.6.2.crop/driver: ivtv-ioctl.c~
Only in ivtv-0.6.2.crop/driver: ivtv-ioctl.o
Only in ivtv-0.6.2.crop/driver: .ivtv-ioctl.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-irq.o
Only in ivtv-0.6.2.crop/driver: .ivtv-irq.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv.ko
Only in ivtv-0.6.2.crop/driver: .ivtv.ko.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-kthreads.o
Only in ivtv-0.6.2.crop/driver: .ivtv-kthreads.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-mailbox.o
Only in ivtv-0.6.2.crop/driver: .ivtv-mailbox.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv.mod.c
Only in ivtv-0.6.2.crop/driver: ivtv.mod.o
Only in ivtv-0.6.2.crop/driver: .ivtv.mod.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv.o
Only in ivtv-0.6.2.crop/driver: .ivtv.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-osd.o
Only in ivtv-0.6.2.crop/driver: .ivtv-osd.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-queue.o
Only in ivtv-0.6.2.crop/driver: .ivtv-queue.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-reset.o
Only in ivtv-0.6.2.crop/driver: .ivtv-reset.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-streams.o
Only in ivtv-0.6.2.crop/driver: .ivtv-streams.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-svnversion.h
Only in ivtv-0.6.2.crop/driver: ivtv-svnversion.h.tmp
Only in ivtv-0.6.2.crop/driver: ivtv-vbi.o
Only in ivtv-0.6.2.crop/driver: .ivtv-vbi.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-video.o
Only in ivtv-0.6.2.crop/driver: .ivtv-video.o.cmd
Only in ivtv-0.6.2.crop/driver: ivtv-yuv.o
Only in ivtv-0.6.2.crop/driver: .ivtv-yuv.o.cmd
Only in ivtv-0.6.2.crop/driver: .tmp_versions
Only in ivtv-0.6.2.crop/i2c-drivers: saa717x.ko
Only in ivtv-0.6.2.crop/i2c-drivers: .saa717x.ko.cmd
Only in ivtv-0.6.2.crop/i2c-drivers: saa717x.mod.c
Only in ivtv-0.6.2.crop/i2c-drivers: saa717x.mod.o
Only in ivtv-0.6.2.crop/i2c-drivers: .saa717x.mod.o.cmd
Only in ivtv-0.6.2.crop/i2c-drivers: saa717x.o
Only in ivtv-0.6.2.crop/i2c-drivers: .saa717x.o.cmd
Only in ivtv-0.6.2.crop/i2c-drivers: .tmp_versions
Only in ivtv-0.6.2.crop/i2c-drivers: upd64031a.ko
Only in ivtv-0.6.2.crop/i2c-drivers: .upd64031a.ko.cmd
Only in ivtv-0.6.2.crop/i2c-drivers: upd64031a.mod.c
Only in ivtv-0.6.2.crop/i2c-drivers: upd64031a.mod.o
Only in ivtv-0.6.2.crop/i2c-drivers: .upd64031a.mod.o.cmd
Only in ivtv-0.6.2.crop/i2c-drivers: upd64031a.o
Only in ivtv-0.6.2.crop/i2c-drivers: .upd64031a.o.cmd
Only in ivtv-0.6.2.crop/i2c-drivers: upd64083.ko
Only in ivtv-0.6.2.crop/i2c-drivers: .upd64083.ko.cmd
Only in ivtv-0.6.2.crop/i2c-drivers: upd64083.mod.c
Only in ivtv-0.6.2.crop/i2c-drivers: upd64083.mod.o
Only in ivtv-0.6.2.crop/i2c-drivers: .upd64083.mod.o.cmd
Only in ivtv-0.6.2.crop/i2c-drivers: upd64083.o
Only in ivtv-0.6.2.crop/i2c-drivers: .upd64083.o.cmd
Only in ivtv-0.6.2.crop/i2c-drivers: wm8739.ko
Only in ivtv-0.6.2.crop/i2c-drivers: .wm8739.ko.cmd
Only in ivtv-0.6.2.crop/i2c-drivers: wm8739.mod.c
Only in ivtv-0.6.2.crop/i2c-drivers: wm8739.mod.o
Only in ivtv-0.6.2.crop/i2c-drivers: .wm8739.mod.o.cmd
Only in ivtv-0.6.2.crop/i2c-drivers: wm8739.o
Only in ivtv-0.6.2.crop/i2c-drivers: .wm8739.o.cmd
Only in ivtv-0.6.2.crop/test: fwapi
Only in ivtv-0.6.2.crop/test: ivtv-pcm-tester
Only in ivtv-0.6.2.crop/test: vbi
Only in ivtv-0.6.2.crop/test: vbi-detect
Only in ivtv-0.6.2.crop/test: vbi-passthrough
Only in ivtv-0.6.2.crop/test: wss
Only in ivtv-0.6.2.crop/utils/cx25840ctl: cmdline.o
Only in ivtv-0.6.2.crop/utils/cx25840ctl: cx25840ctl
Only in ivtv-0.6.2.crop/utils/cx25840ctl: cx25840ctl.o
Only in ivtv-0.6.2.crop/utils/cx25840ctl: cx25840-registers.o
Only in ivtv-0.6.2.crop/utils: enc_chann.o
Only in ivtv-0.6.2.crop/utils: enc_mindex.o
Only in ivtv-0.6.2.crop/utils: encoder.o
Only in ivtv-0.6.2.crop/utils: ivtvctl
diff -wpr ivtv-0.6.2/utils/ivtvctl.c ivtv-0.6.2.crop/utils/ivtvctl.c
*** ivtv-0.6.2/utils/ivtvctl.c	2006-03-24 18:21:04.000000000 -0600
--- ivtv-0.6.2.crop/utils/ivtvctl.c	2006-06-03 15:18:09.000000000 -0500
*************** static int option_version = 0;
*** 113,118 ****
--- 113,120 ----
  static int option_setYuvMode = 0;
  static int option_getYuvMode = 0;
  static int option_log_status = 0;
+ static int option_get_crop = 0;
+ static int option_set_crop = 0;
  
  /* Codec's specified */
  #define CAspect                 (1L<<1)
*************** static int option_log_status = 0;
*** 139,144 ****
--- 141,153 ----
  #define FMTWidth                (1L<<0)
  #define FMTHeight               (1L<<1)
  
+ /* crops specified */
+ #define CROPLeft                (1L<<0)
+ #define CROPTop                 (1L<<1)
+ #define CROPWidth               (1L<<2)
+ #define CROPHeight              (1L<<3)
+ 
+ 
  static struct option long_options[] = {
          /* Please keep in alphabetical order of the short option.
             That makes it easier to see which options are still free. */
*************** static struct option long_options[] = {
*** 154,159 ****
--- 163,170 ----
          {"get-debug", no_argument, 0, OptGetDebugLevel},
          {"get-format", no_argument, 0, OptGetFormat},
          {"set-format", required_argument, 0, OptSetFormat},
+         {"get-crop", no_argument, &option_get_crop, 1},
+         {"set-crop", required_argument, &option_set_crop, 1},
          {"list-dec-registers", no_argument, 0, OptListDecRegisters},
          {"set-dec-registers", required_argument, 0, OptSetDecRegister},
          {"list-itvc-registers", required_argument, 0, OptListITVCRegisters},
*************** void usage(void)
*** 238,243 ****
--- 249,257 ----
          printf("  -F, --get-format   query the current data format [VIDIOC_G_FMT]\n");
          printf("  -f, --set-format=width=<x>,height=<y>\n");
          printf("                     set the current data format [VIDIOC_S_FMT]\n");
+         printf("      --get-crop     query the current data cropping rectangle [VIDIOC_G_CROP]\n");
+         printf("      --set-crop=left=<l>,top=<t>,width=<x>,height=<y>\n");
+         printf("                     set the current cropping rectangle [VIDIOC_S_CROP]\n");
          printf("  -h, --help         display this help message\n");
          printf("  -K, --passthrough=<mode>\n");
          printf("                     set passthrough mode: 1 = on, 0 = off [IVTV_IOC_PASSTHROUGH]\n");
*************** int printfmt(struct v4l2_format vfmt)
*** 368,373 ****
--- 382,420 ----
          return 0;
  }
  
+ int printcrop(struct v4l2_crop vcrop)
+ {
+         switch (vcrop.type) {
+         case 1:
+                 printf("\tType   : Video Capture\n");
+                 printf("\tLeft   : %d\n", vcrop.c.left);
+                 printf("\tTop    : %d\n", vcrop.c.top);
+                 printf("\tWidth  : %d\n", vcrop.c.width);
+                 printf("\tHeight : %d\n", vcrop.c.height);
+                 break;
+         case 2:
+                 printf("\tType   : Video Output\n");
+                 break;
+         case 3:
+                 printf("\tType   : Video Overlay\n");
+                 break;
+         case 4:
+                 printf("\tType   : VBI Capture\n");
+                 break;
+         case 5:
+                 printf("\tType   : VBI Output\n");
+                 break;
+         case 0x80:
+                 printf("\tType   : Private\n");
+                 break;
+         default:
+                 printf("\tType   : Unknown: %d\n", vcrop.type);
+                 return -1;
+                 break;
+         }
+         return 0;
+ }
+ 
  char *pts_to_string(char *str, unsigned long pts)
  {
          static char buf[256];
*************** int main(int argc, char **argv)
*** 555,560 ****
--- 602,611 ----
                  "loudness",
  #define SUB_DIR                         38
                  "dir",
+ #define SUB_LEFT                        39
+                 "left",
+ #define SUB_TOP                         40
+                 "top",
                  NULL
          };
  
*************** int main(int argc, char **argv)
*** 565,570 ****
--- 616,623 ----
          unsigned int set_yuvMode = 0;
          /* bitfield for fmts */
          unsigned int set_fmts = 0;
+         /* bitfield for crops */
+         unsigned int set_crops = 0;
  
          int mode = V4L2_TUNER_MODE_STEREO;      /* set audio mode */
  
*************** int main(int argc, char **argv)
*** 575,580 ****
--- 628,634 ----
          struct ivtv_ioctl_yuv_interlace yuv_mode = { 0, 0 };
          struct v4l2_format vfmt;        /* set_format/get_format */
          struct v4l2_format vbi_fmt;     /* set_format/get_format for sliced VBI */
+         struct v4l2_crop vcrop;         /* set_crop/get_crop */
          struct v4l2_control ctrl;       /* set_ctrl/get_ctrls */
          struct ivtv_ioctl_register saa7115_reg;
          struct ivtv_ioctl_register itvc_reg;
*************** int main(int argc, char **argv)
*** 657,662 ****
--- 711,775 ----
                                  }
                          }
                      }
+                     else if (option_set_crop == 1)
+                     {
+                         subs = optarg;
+                         while (*subs != '\0') {
+                                 switch (getsubopt(&subs, subopts, &value)) {
+                                 case SUB_LEFT:
+                                         if (value == NULL) {
+                                                 fprintf(stderr,
+                                                         "No value given to suboption <left>\n");
+                                                 usage();
+                                                 exit(1);
+                                         }
+                                         vcrop.c.left =
+                                             strtol(value, 0L, 0);
+                                         set_crops |= CROPLeft;
+                                         break;
+                                 case SUB_TOP:
+                                         if (value == NULL) {
+                                                 fprintf(stderr,
+                                                         "No value given to suboption <top>\n");
+                                                 usage();
+                                                 exit(1);
+                                         }
+                                         vcrop.c.top =
+                                             strtol(value, 0L, 0);
+                                         set_crops |= CROPTop;
+                                         break;
+                                 case SUB_WIDTH:
+                                         if (value == NULL) {
+                                                 fprintf(stderr,
+                                                         "No value given to suboption <width>\n");
+                                                 usage();
+                                                 exit(1);
+                                         }
+                                         vcrop.c.width =
+                                             strtol(value, 0L, 0);
+                                         set_crops |= CROPWidth;
+                                         break;
+                                 case SUB_HEIGHT:
+                                         if (value == NULL) {
+                                                 fprintf(stderr,
+                                                         "No value given to suboption <height>\n");
+                                                 usage();
+                                                 exit(1);
+                                         }
+                                         vcrop.c.height =
+                                             strtol(value, 0L, 0);
+                                         set_crops |= CROPHeight;
+                                         break;
+                                 default:
+                                         fprintf(stderr,
+                                                 "Invalid suboptions specified\n");
+                                         usage();
+                                         exit(1);
+                                         break;
+                                 }
+                         }
+ 
+                     }   
                      break;
                  case OptHelp:
                          usage();
*************** int main(int argc, char **argv)
*** 1311,1316 ****
--- 1424,1461 ----
                  }
          }
  
+         if (option_set_crop) {
+                 struct v4l2_crop in_vcrop;
+                 printf("ioctl: VIDIOC_S_CROP\n");
+                 in_vcrop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                 if (ioctl(fd, VIDIOC_G_CROP, &in_vcrop) < 0)
+                         fprintf(stderr, "ioctl: VIDIOC_G_CROP failed\n");
+                 else {
+                         printf("\tBefore:\n");
+                         if (printcrop(in_vcrop) != 0)
+                                 fprintf(stderr, "error printing result\n");
+                         if (set_crops & CROPLeft)
+                                 in_vcrop.c.left = vcrop.c.left;
+                         if (set_crops & CROPTop)
+                                 in_vcrop.c.top = vcrop.c.top;
+                         if (set_crops & CROPWidth)
+                                 in_vcrop.c.width = vcrop.c.width;
+                         if (set_crops & CROPHeight)
+                                 in_vcrop.c.height = vcrop.c.height;
+                         if (ioctl(fd, VIDIOC_S_CROP, &in_vcrop) < 0)
+                                 fprintf(stderr, "ioctl: VIDIOC_S_CROP failed\n");
+                         vcrop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                         if (ioctl(fd, VIDIOC_G_CROP, &vcrop) < 0)
+                                 fprintf(stderr, "ioctl: VIDIOC_G_CROP failed\n");
+                         else {
+                                 printf("\n\tAfter:\n");
+                                 if (printcrop(vcrop) != 0)
+                                         fprintf(stderr,
+                                                 "error printing result\n");
+                         }
+                 }
+         }
+ 
          if (options[OptReloadFW]) {
                  doioctl(fd, IVTV_IOC_RELOAD_FW, NULL, "IVTV_IOC_RELOAD_FW");
          }
*************** int main(int argc, char **argv)
*** 1431,1436 ****
--- 1576,1587 ----
                          if (printfmt(vfmt) != 0)
                                  fprintf(stderr, "error printing result\n");
          }
+         if (option_get_crop) {
+                 vcrop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                 if (doioctl(fd, VIDIOC_G_CROP, &vcrop, "VIDIOC_G_CROP") == 0)
+                         if (printcrop(vcrop) != 0)
+                                 fprintf(stderr, "error printing result\n");
+         }
          if (options[OptListITVCRegisters]) {
                  printf("ioctl: IVTV_IOC_G_ITVC_REG\n");
                  printf("                00       04       08       0C       10       14       18       1C");
Only in ivtv-0.6.2.crop/utils: ivtvctl.c~
Only in ivtv-0.6.2.crop/utils: ivtvctl.o
Only in ivtv-0.6.2.crop/utils: ivtv-detect
Only in ivtv-0.6.2.crop/utils: ivtv-encoder
Only in ivtv-0.6.2.crop/utils: ivtvfbctl
Only in ivtv-0.6.2.crop/utils: ivtv-mpegindex
Only in ivtv-0.6.2.crop/utils: ivtvplay
Only in ivtv-0.6.2.crop/utils: ivtv-radio
Only in ivtv-0.6.2.crop/utils/ivtv-tune: cmdline.o
Only in ivtv-0.6.2.crop/utils/ivtv-tune: frequencies.o
Only in ivtv-0.6.2.crop/utils/ivtv-tune: ivtv-tune
Only in ivtv-0.6.2.crop/utils/ivtv-tune: ivtv-tune.o
Only in ivtv-0.6.2.crop/utils/ivtv-tune: xawtv_parseconfig.o
Only in ivtv-0.6.2.crop/utils: ttt
_______________________________________________
ivtv-devel mailing list
[email protected]
http://ivtvdriver.org/mailman/listinfo/ivtv-devel

Reply via email to