# Original patch by Jim Studt on Linux-uvc-devel diff -ur trunk.232/uvc_v4l2.c trunk.232.JPEGCOMP/uvc_v4l2.c --- trunk.232/uvc_v4l2.c 2008-07-18 22:12:57.000000000 +0200 +++ trunk.232.JPEGCOMP/uvc_v4l2.c 2008-07-18 22:24:14.000000000 +0200 @@ -332,6 +332,45 @@ return 0; } + +static int uvc_v4l2_get_jpegcompression(struct uvc_video_device *video, + struct v4l2_jpegcompression *parm) +{ + memset(parm, 0, sizeof *parm); + parm->quality = video->streaming->ctrl.wCompQuality/100; /* scale from UVC 10000 to familiar 10 */ + // Are DQT and DRI required in UVC? Maybe we should turn on their bits in jpeg_markers? + + return 0; +} + +static int uvc_v4l2_set_jpegcompression(struct uvc_video_device *video, + struct v4l2_jpegcompression *parm) +{ + struct uvc_streaming_control probe; + int ret; + int quality; + + memcpy(&probe, &video->streaming->ctrl, sizeof probe); + quality = parm->quality * 100; /* scale from famliar 100 to UVC 10000 */ + + uvc_trace(UVC_TRACE_FORMAT, "Setting jpeg quality to %d.\n", quality); + + probe.wCompQuality = quality; + /* Probe the device with the new settings. */ + if ((ret = uvc_probe_video(video, &probe)) < 0) + return ret; + + /* Commit the new settings. */ + if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0) + return ret; + + memcpy(&video->streaming->ctrl, &probe, sizeof probe); + + return 0; +} + + + /* ------------------------------------------------------------------------ * Privilege management */ @@ -793,6 +832,16 @@ break; } + case VIDIOC_G_JPEGCOMP: + return uvc_v4l2_get_jpegcompression(video, (struct v4l2_jpegcompression*)arg); + + case VIDIOC_S_JPEGCOMP: + if ((ret = uvc_acquire_privileges(handle)) < 0) + return ret; + + return uvc_v4l2_set_jpegcompression(video, (struct v4l2_jpegcompression*)arg); + + /* Get & Set streaming parameters */ case VIDIOC_G_PARM: return uvc_v4l2_get_streamparm(video, arg); diff -ur trunk.232/uvc_video.c trunk.232.JPEGCOMP/uvc_video.c --- trunk.232/uvc_video.c 2008-07-18 22:12:57.000000000 +0200 +++ trunk.232.JPEGCOMP/uvc_video.c 2008-07-18 22:35:17.000000000 +0200 @@ -185,7 +185,7 @@ int uvc_probe_video(struct uvc_video_device *video, struct uvc_streaming_control *probe) { - struct uvc_streaming_control probe_min, probe_max; + struct uvc_streaming_control probe_min, probe_max, probe_res; __u16 bandwidth; unsigned int i; int ret; @@ -207,11 +207,39 @@ ret = uvc_get_video_ctrl(video, &probe_min, 1, GET_MIN); if (ret < 0) goto done; - ret = uvc_get_video_ctrl(video, &probe_max, 1, GET_MAX); + + /* ret = uvc_get_video_ctrl(video, &probe_max, 1, GET_MAX); */ + + ret = uvc_get_video_ctrl(video, &probe_max, 1, GET_MAX); + if (ret < 0) + goto done; + + ret = uvc_get_video_ctrl(video, &probe_res, 1, GET_RES); if (ret < 0) goto done; - probe->wCompQuality = probe_max.wCompQuality; + + /* pin wCompQuality to the legal range */ + if ( probe->wCompQuality < probe_min.wCompQuality) probe->wCompQuality = probe_min.wCompQuality; + else if ( probe->wCompQuality > probe_max.wCompQuality) probe->wCompQuality = probe_max.wCompQuality; + else { + int range, steps, step_size; +/* probe->wCompQuality = probe_max.wCompQuality; */ + /* this mess of code makes sure wCompQuality lands on one of the legal values */ + step_size = probe_res.wCompQuality; + range = probe_max.wCompQuality - probe_min.wCompQuality; + if ( range != 0 && step_size != 0) { + steps = range / step_size; + probe->wCompQuality = probe_min.wCompQuality + + (probe->wCompQuality - probe_min.wCompQuality + step_size/2) *steps/range*step_size; + } else { + probe->wCompQuality = probe_max.wCompQuality; + } + } + + + + } for (i = 0; i < 2; ++i) { @@ -234,7 +262,8 @@ /* TODO: negotiate compression parameters */ probe->wKeyFrameRate = probe_min.wKeyFrameRate; probe->wPFrameRate = probe_min.wPFrameRate; - probe->wCompQuality = probe_max.wCompQuality; + //probe->wCompQuality = probe_max.wCompQuality; + probe->wCompQuality = probe_min.wCompQuality; probe->wCompWindowSize = probe_min.wCompWindowSize; }