usbvision: disable scaling for Nogatech MicroCam
PATCH RESEND 1/1 usbvision: disable scaling for Nogatech MicroCam
Scaling causes bad artifacts (horizontal lines) with compression at least with Nogatech MicroCam so disable it (for this HW).
This also fixes messed up image with some programs (Cheese with 160x120, Adobe Flash). HW seems to support only image widths that are multiple of 64 but the driver does not account that in vidioc_try_fmt_vid_cap(). Cheese calls try_fmt with 160x120, succeeds and then assumes that it really gets data in that resolution - but it gets 128x120 instead. Don't know if this affects other usbvision devices, it would be great if someone could test it.
drivers/media/video/usbvision/usbvision-video.c renamed from drivers/media/video/usbvision//usbvision-video.c +10 -0
@@ -924,6 +924,11 @@ static int vidioc_try_fmt_vid_cap(structRESTRICT_TO_RANGE (vf->fmt.pix.width,MIN_FRAME_WIDTH ,MAX_FRAME_WIDTH );RESTRICT_TO_RANGE (vf->fmt.pix.height,MIN_FRAME_HEIGHT ,MAX_FRAME_HEIGHT ); +if (usbvision_device_data[usbvision->dev_model].codec ==CODEC_WEBCAM ) { + vf->fmt.pix.width =MAX_FRAME_WIDTH ; + vf->fmt.pix.height =MAX_FRAME_HEIGHT ; + } + vf->fmt.pix.bytesperline = vf->fmt.pix.width* usbvision->palette.bytes_per_pixel; vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height;
@@ -952,6 +957,11 @@ static int vidioc_s_fmt_vid_cap(struct f usbvision->cur_frame =NULL ; +if (usbvision_device_data[usbvision->dev_model].codec ==CODEC_WEBCAM ) { + vf->fmt.pix.width =MAX_FRAME_WIDTH ; + vf->fmt.pix.height =MAX_FRAME_HEIGHT ; + } +/* by now we are committed to the new data... */ usbvision_set_output (usbvision, vf->fmt.pix.width, vf->fmt.pix.height);
Signature · 1 line
Ondrej Zary
Quoted 41 lines · Ondrej Zary
Scaling causes bad artifacts (horizontal lines) with compression at least with Nogatech MicroCam so disable it (for this HW).
This also fixes messed up image with some programs (Cheese with 160x120, Adobe Flash). HW seems to support only image widths that are multiple of 64 but the driver does not account that in
vidioc_try_fmt_vid_cap(). Cheese callstry_fmtwith 160x120, succeeds and then assumes that it really gets data in that resolution - but it gets 128x120 instead. Don't know if this affects other usbvision devices, it would be great if someone could test it.Signed-off-by Ondrej Zary <[email protected]>diff -urp linux-2.6.39-rc2-/drivers/media/video/usbvision//usbvision-video.c
linux-2.6.39-rc2/drivers/media/video/usbvision/usbvision-video.cdrivers/media/video/usbvision/usbvision-video.c 2011-07-16 16:36:43.000000000 +0200 renamed from drivers/media/video/usbvision//usbvision-video.c 2011-07-16 16:42:35.000000000 +0200 +5
-0@@ -924,6 +924,11 @@ static int vidioc_try_fmt_vid_cap(struct RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT); + if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { + vf->fmt.pix.width = MAX_FRAME_WIDTH; + vf->fmt.pix.height = MAX_FRAME_HEIGHT; + } +vf->fmt.pix.bytesperline = vf->fmt.pix.width*
usbvision->palette.bytes_per_pixel;vf->fmt.pix.sizeimage= vf->fmt.pix.bytesperline*vf->fmt.pix.height;drivers/media/video/usbvision/usbvision-video.c 2011-07-16 16:36:43.000000000 +0200 renamed from drivers/media/video/usbvision//usbvision-video.c 2011-07-16 16:42:35.000000000 +0200 +5
-1@@ -952,6 +957,11 @@ static int vidioc_s_fmt_vid_cap(struct f usbvision->cur_frame = NULL; + if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { + vf->fmt.pix.width = MAX_FRAME_WIDTH; + vf->fmt.pix.height = MAX_FRAME_HEIGHT; + } + /* by now we are committed to the new data... */ usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); --
Quoted 1 line
Ondrej Zary
Hello Ondrej,
Drivers are permitted to return a different resolution than what the application provided in the S_FMT call. It is the responsibility of the application to look at the struct after the ioctl() call and if the values are not what it expects to then accommodate the change.
In other words, this sounds like a bug in Cheese.
Devin
Signature · 2 lines
Devin J. Heitmueller - Kernel Labs http://www.kernellabs.com
Quoted 46 lines · On Friday 22 July 2011 22:06:59 Devin Heitmueller wrote:
Quoted 41 lines · Ondrej Zary
Scaling causes bad artifacts (horizontal lines) with compression at least with Nogatech MicroCam so disable it (for this HW).
This also fixes messed up image with some programs (Cheese with 160x120, Adobe Flash). HW seems to support only image widths that are multiple of 64 but the driver does not account that in
vidioc_try_fmt_vid_cap(). Cheese callstry_fmtwith 160x120, succeeds and then assumes that it really gets data in that resolution - but it gets 128x120 instead. Don't know if this affects other usbvision devices, it would be great if someone could test it.Signed-off-by Ondrej Zary <[email protected]>diff -urp linux-2.6.39-rc2-/drivers/media/video/usbvision//usbvision-video.c
linux-2.6.39-rc2/drivers/media/video/usbvision/usbvision-video.cdrivers/media/video/usbvision/usbvision-video.c 2011-07-16 16:36:43.000000000 +0200 renamed from drivers/media/video/usbvision//usbvision-video.c 2011-07-16 16:42:35.000000000 +0200 +5
-0@@ -924,6 +924,11 @@ static int vidioc_try_fmt_vid_cap(struct RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT); + if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { + vf->fmt.pix.width = MAX_FRAME_WIDTH; + vf->fmt.pix.height = MAX_FRAME_HEIGHT; + } +vf->fmt.pix.bytesperline = vf->fmt.pix.width*
usbvision->palette.bytes_per_pixel;vf->fmt.pix.sizeimage= vf->fmt.pix.bytesperline*vf->fmt.pix.height;drivers/media/video/usbvision/usbvision-video.c 2011-07-16 16:36:43.000000000 +0200 renamed from drivers/media/video/usbvision//usbvision-video.c 2011-07-16 16:42:35.000000000 +0200 +5
-1@@ -952,6 +957,11 @@ static int vidioc_s_fmt_vid_cap(struct f usbvision->cur_frame = NULL; + if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { + vf->fmt.pix.width = MAX_FRAME_WIDTH; + vf->fmt.pix.height = MAX_FRAME_HEIGHT; + } + /* by now we are committed to the new data... */ usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); --Quoted 1 line
Ondrej Zary
Hello Ondrej,
Quoted 6 lines
Drivers are permitted to return a different resolution than what the application provided in the
S_FMTcall. It is the responsibility of the application to look at the struct after theioctl()call and if the values are not what it expects to then accommodate the change.In other words, this sounds like a bug in Cheese.
Seems that this bug is widespread - the same problem appears also in guvcview and adobe flash. I think that the driver is broken too - it should return corrected resolution in TRY_FMT.
Quoted 2 lines
Devin
Signature · 1 line
Ondrej Zary
Quoted 3 lines · Ondrej Zary
Seems that this bug is widespread - the same problem appears also in guvcview and adobe flash. I think that the driver is broken too - it should return corrected resolution in
TRY_FMT.
Well, if the driver does not return the resolution it is actually capturing in, then that indeed is a driver bug. That's a different issue though than what your patch proposed.
You should make the TRY_FMT call specifying an invalid resolution and see if it returns the real resolution the device will capture at. If it doesn't, then fix *that* bug.
The application needs to know the capturing resolution, so it's possible that it does properly handle the driver passing back the real resolution and the driver is at fault, in which case no change is needed to the app at all.
Devin
Signature · 2 lines
Devin J. Heitmueller - Kernel Labs http://www.kernellabs.com
Quoted 5 lines · On Friday 22 July 2011 23:31:46 Devin Heitmueller wrote:
Quoted 3 lines · Ondrej Zary
Seems that this bug is widespread - the same problem appears also in guvcview and adobe flash. I think that the driver is broken too - it should return corrected resolution in
TRY_FMT.
Quoted 7 lines
Well, if the driver does not return the resolution it is actually capturing in, then that indeed is a driver bug. That's a different issue though than what your patch proposed.
You should make the
TRY_FMTcall specifying an invalid resolution and see if it returns the real resolution the device will capture at. If it doesn't, then fix *that* bug.
It does not, there's no code that would do that. I actually fixed that only to find out that the scaling is unusable at least with the MicroCam because of black horizontal lines that appear in the image (amount of the lines depend on the scaling factor). So I just disabled the scaling completely for MicroCam.
I also don't know if the multiple-of-64 width limit is valid for all usbvision devices - that's why I haven't posted patch to fix this.
Quoted 7 lines
The application needs to know the capturing resolution, so it's possible that it does properly handle the driver passing back the real resolution and the driver is at fault, in which case no change is needed to the app at all.
Devin
Signature · 1 line
Ondrej Zary
Em 22-07-2011 18:44, Ondrej Zary escreveu:
Quoted 14 lines · On Friday 22 July 2011 23:31:46 Devin Heitmueller wrote:
Quoted 5 lines · Ondrej Zary
Quoted 3 lines
Seems that this bug is widespread - the same problem appears also in guvcview and adobe flash. I think that the driver is broken too - it should return corrected resolution in
TRY_FMT.Quoted 7 lines
Well, if the driver does not return the resolution it is actually capturing in, then that indeed is a driver bug. That's a different issue though than what your patch proposed.
You should make the
TRY_FMTcall specifying an invalid resolution and see if it returns the real resolution the device will capture at. If it doesn't, then fix *that* bug.
Quoted 13 lines
It does not, there's no code that would do that. I actually fixed that only to find out that the scaling is unusable at least with the MicroCam because of black horizontal lines that appear in the image (amount of the lines depend on the scaling factor). So I just disabled the scaling completely for MicroCam.
I also don't know if the multiple-of-64 width limit is valid for all usbvision devices - that's why I haven't posted patch to fix this.
Quoted 4 lines
The application needs to know the capturing resolution, so it's possible that it does properly handle the driver passing back the real resolution and the driver is at fault, in which case no change is needed to the app at all.
Well, for sure you don't need to touch at s_fmt, as it calls try_fmt. Also, if the problem is that the scaler requrires that the vertical resolution to be multiple of some limit, a patch like the one bellow would do a better job:
drivers/media/video/usbvision/usbvision-video.c +3 -0
@@ -922,6 +922,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,RESTRICT_TO_RANGE (vf->fmt.pix.width,MIN_FRAME_WIDTH ,MAX_FRAME_WIDTH );RESTRICT_TO_RANGE (vf->fmt.pix.height,MIN_FRAME_HEIGHT ,MAX_FRAME_HEIGHT ); +/* FIXME: please correct the minimum resolution here */ + vf->fmt.pix.width &= ~0x01 ; + vf->fmt.pix.bytesperline = vf->fmt.pix.width* usbvision->palette.bytes_per_pixel; vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height;
Some scalers require an even vertical resolution. So, you'll need to adjust the above, according with the restrictions you may have on the scaler your webcam has.
Btw, V4L2 core defines a macro for such type of adjustments. For example, em28xx uses it as:
/* width must even because of the YUYV format height must be even because of interlacing */ v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);
(
So, a better fix would be to remove the RESTRICT_TO_RANGE() calls, and use the v4l_bound_align_image() macro instead, filled with the needed restrictions, like:
v4l_bound_align_image(&width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH, 1, &height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT, 0);
-
[usbvision] Fix width/height scaling limits
It assumes that both just width is required to be even number.
NOT TESTED.
drivers/media/video/usbvision/usbvision-video.c +5 -2
@@ -919,8 +919,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,/* robustness */ if (format_idx ==USBVISION_SUPPORTED_PALETTES )return -EINVAL ; -RESTRICT_TO_RANGE (vf->fmt.pix.width,MIN_FRAME_WIDTH ,MAX_FRAME_WIDTH ); -RESTRICT_TO_RANGE (vf->fmt.pix.height,MIN_FRAME_HEIGHT ,MAX_FRAME_HEIGHT ); + +v4l_bound_align_image (&vf->fmt.pix.width, +MIN_FRAME_WIDTH ,MAX_FRAME_WIDTH ,1 , + &vf->fmt.pix.height, +MIN_FRAME_HEIGHT ,MAX_FRAME_HEIGHT ,0 ,0 ); vf->fmt.pix.bytesperline = vf->fmt.pix.width* usbvision->palette.bytes_per_pixel;
Offtopic. Mauro is your pull request ready ? the merge window is open.
Em 27-07-2011 14:15, Anca Emanuel escreveu:
Quoted 1 line
Offtopic. Mauro is your pull request ready ? the merge window is open.
Working on it.
Cheers,
Mauro
Quoted 69 lines · On Wednesday 27 July 2011 17:03:06 Mauro Carvalho Chehab wrote:
Em 22-07-2011 18:44, Ondrej Zary escreveu:
Quoted 14 lines · On Friday 22 July 2011 23:31:46 Devin Heitmueller wrote:
Quoted 5 lines · Ondrej Zary
Quoted 3 lines
Seems that this bug is widespread - the same problem appears also in guvcview and adobe flash. I think that the driver is broken too - it should return corrected resolution in
TRY_FMT.Quoted 7 lines
Well, if the driver does not return the resolution it is actually capturing in, then that indeed is a driver bug. That's a different issue though than what your patch proposed.
You should make the
TRY_FMTcall specifying an invalid resolution and see if it returns the real resolution the device will capture at. If it doesn't, then fix *that* bug.Quoted 13 lines
It does not, there's no code that would do that. I actually fixed that only to find out that the scaling is unusable at least with the MicroCam because of black horizontal lines that appear in the image (amount of the lines depend on the scaling factor). So I just disabled the scaling completely for MicroCam.
I also don't know if the multiple-of-64 width limit is valid for all usbvision devices - that's why I haven't posted patch to fix this.
Quoted 4 lines
The application needs to know the capturing resolution, so it's possible that it does properly handle the driver passing back the real resolution and the driver is at fault, in which case no change is needed to the app at all.
Well, for sure you don't need to touch at
s_fmt, as it callstry_fmt. Also, if the problem is that the scaler requrires that the vertical resolution to be multiple of some limit, a patch like the one bellow would do a better job:drivers/media/video/usbvision/usbvision-video.c +3
-0@@ -922,6 +922,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,RESTRICT_TO_RANGE (vf->fmt.pix.width,MIN_FRAME_WIDTH ,MAX_FRAME_WIDTH );RESTRICT_TO_RANGE (vf->fmt.pix.height,MIN_FRAME_HEIGHT ,MAX_FRAME_HEIGHT ); +/* FIXME: please correct the minimum resolution here */ + vf->fmt.pix.width &= ~0x01 ; + vf->fmt.pix.bytesperline = vf->fmt.pix.width* usbvision->palette.bytes_per_pixel; vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height;Some scalers require an even vertical resolution. So, you'll need to adjust the above, according with the restrictions you may have on the scaler your webcam has.
Btw, V4L2 core defines a macro for such type of adjustments. For example, em28xx uses it as:
/* width must even because of the YUYV format height must be even because of interlacing */ v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);(
So, a better fix would be to remove the
RESTRICT_TO_RANGE()calls, and use thev4l_bound_align_image()macro instead, filled with the needed restrictions, like:v4l_bound_align_image(&width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH, 1, &height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT, 0);
Quoted 5 lines
-
[usbvision] Fix width/height scaling limits
It assumes that both just width is required to be even number.
Width on the Nogatech MicroCam is limited to multiples of 64 (e.g. if you set the width to 160, you get 128 instead). But the scaled output is useless because of black horizontal lines that scaling produces with compression (which is enabled by default). Probably nobody wants to disable the compression as the framerate is very low without it.
I don't know about other usbvision devices. We shouldn't change the code for all of them without testing.
Quoted 28 lines
NOT TESTED.
Signed-of-by Mauro Carvalho Chehab <[email protected]>drivers/media/video/usbvision/usbvision-video.c +5
-3@@ -919,8 +919,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,/* robustness */ if (format_idx ==USBVISION_SUPPORTED_PALETTES )return -EINVAL ; -RESTRICT_TO_RANGE (vf->fmt.pix.width,MIN_FRAME_WIDTH ,MAX_FRAME_WIDTH ); -RESTRICT_TO_RANGE (vf->fmt.pix.height,MIN_FRAME_HEIGHT ,MAX_FRAME_HEIGHT ); + +v4l_bound_align_image (&vf->fmt.pix.width, +MIN_FRAME_WIDTH ,MAX_FRAME_WIDTH ,1 , + &vf->fmt.pix.height, +MIN_FRAME_HEIGHT ,MAX_FRAME_HEIGHT ,0 ,0 ); vf->fmt.pix.bytesperline = vf->fmt.pix.width* usbvision->palette.bytes_per_pixel; --To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signature · 1 line
Ondrej Zary
Em 01-08-2011 15:50, Ondrej Zary escreveu:
Quoted 72 lines · On Wednesday 27 July 2011 17:03:06 Mauro Carvalho Chehab wrote:
Quoted 71 lines
Em 22-07-2011 18:44, Ondrej Zary escreveu:
Quoted 14 lines · On Friday 22 July 2011 23:31:46 Devin Heitmueller wrote:
Quoted 5 lines · Ondrej Zary
Quoted 3 lines
Seems that this bug is widespread - the same problem appears also in guvcview and adobe flash. I think that the driver is broken too - it should return corrected resolution in
TRY_FMT.Quoted 7 lines
Well, if the driver does not return the resolution it is actually capturing in, then that indeed is a driver bug. That's a different issue though than what your patch proposed.
You should make the
TRY_FMTcall specifying an invalid resolution and see if it returns the real resolution the device will capture at. If it doesn't, then fix *that* bug.Quoted 13 lines
It does not, there's no code that would do that. I actually fixed that only to find out that the scaling is unusable at least with the MicroCam because of black horizontal lines that appear in the image (amount of the lines depend on the scaling factor). So I just disabled the scaling completely for MicroCam.
I also don't know if the multiple-of-64 width limit is valid for all usbvision devices - that's why I haven't posted patch to fix this.
Quoted 4 lines
The application needs to know the capturing resolution, so it's possible that it does properly handle the driver passing back the real resolution and the driver is at fault, in which case no change is needed to the app at all.
Well, for sure you don't need to touch at
s_fmt, as it callstry_fmt. Also, if the problem is that the scaler requrires that the vertical resolution to be multiple of some limit, a patch like the one bellow would do a better job:drivers/media/video/usbvision/usbvision-video.c +3
-0@@ -922,6 +922,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,RESTRICT_TO_RANGE (vf->fmt.pix.width,MIN_FRAME_WIDTH ,MAX_FRAME_WIDTH );RESTRICT_TO_RANGE (vf->fmt.pix.height,MIN_FRAME_HEIGHT ,MAX_FRAME_HEIGHT ); +/* FIXME: please correct the minimum resolution here */ + vf->fmt.pix.width &= ~0x01 ; + vf->fmt.pix.bytesperline = vf->fmt.pix.width* usbvision->palette.bytes_per_pixel; vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height;Some scalers require an even vertical resolution. So, you'll need to adjust the above, according with the restrictions you may have on the scaler your webcam has.
Btw, V4L2 core defines a macro for such type of adjustments. For example, em28xx uses it as:
/* width must even because of the YUYV format height must be even because of interlacing */ v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);(
So, a better fix would be to remove the
RESTRICT_TO_RANGE()calls, and use thev4l_bound_align_image()macro instead, filled with the needed restrictions, like:v4l_bound_align_image(&width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH, 1, &height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT, 0);-
Quoted 8 lines
Quoted 3 lines
[usbvision] Fix width/height scaling limits
It assumes that both just width is required to be even number.
Width on the Nogatech MicroCam is limited to multiples of 64 (e.g. if you set the width to 160, you get 128 instead). But the scaled output is useless because of black horizontal lines that scaling produces with compression (which is enabled by default).
Ok. This seems to be either a sensor or a bridge problem. So, it is not specific to Nogatech.
Quoted 2 lines
Probably nobody wants to disable the compression as the framerate is very low without it.
Yet, it may make sense for some applications, like surveillance cameras or telescopes. If the driver already supports compression to be disabled, maybe the right thing to do would be to allow scaling only if compression is disabled, for the devices that have the same bridge and sensor.
Quoted 36 lines
I don't know about other usbvision devices. We shouldn't change the code for all of them without testing.
Quoted 28 lines
NOT TESTED.
Signed-of-by Mauro Carvalho Chehab <[email protected]>drivers/media/video/usbvision/usbvision-video.c +5
-3@@ -919,8 +919,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,/* robustness */ if (format_idx ==USBVISION_SUPPORTED_PALETTES )return -EINVAL ; -RESTRICT_TO_RANGE (vf->fmt.pix.width,MIN_FRAME_WIDTH ,MAX_FRAME_WIDTH ); -RESTRICT_TO_RANGE (vf->fmt.pix.height,MIN_FRAME_HEIGHT ,MAX_FRAME_HEIGHT ); + +v4l_bound_align_image (&vf->fmt.pix.width, +MIN_FRAME_WIDTH ,MAX_FRAME_WIDTH ,1 , + &vf->fmt.pix.height, +MIN_FRAME_HEIGHT ,MAX_FRAME_HEIGHT ,0 ,0 ); vf->fmt.pix.bytesperline = vf->fmt.pix.width* usbvision->palette.bytes_per_pixel; --To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/