Hi,

On 07/08/2014 01:04 PM, Hans Verkuil wrote:
> libv4lconvert did not support the extended control API so qv4l2, which
> uses it, didn't work properly with libv4l2 since passing software
> emulated controls using the extended control API will fail as those
> controls are obviously not known to the driver.
> 
> This patch adds support for this API.
> 
> Signed-off-by: Hans Verkuil <hans.verk...@cisco.com>

Looks good, feel free to push:

Reviewed by: Hans de Goede <hdego...@redhat.com>

Regards,

Hans

> ---
>  lib/include/libv4lconvert.h               |   6 ++
>  lib/libv4l2/libv4l2.c                     |  15 ++++
>  lib/libv4lconvert/control/libv4lcontrol.c | 141 
> ++++++++++++++++++++++++++++++
>  lib/libv4lconvert/control/libv4lcontrol.h |   3 +
>  lib/libv4lconvert/libv4lconvert.c         |  15 ++++
>  5 files changed, 180 insertions(+)
> 
> diff --git a/lib/include/libv4lconvert.h b/lib/include/libv4lconvert.h
> index 2c1f199..e94d3bd 100644
> --- a/lib/include/libv4lconvert.h
> +++ b/lib/include/libv4lconvert.h
> @@ -132,6 +132,12 @@ LIBV4L_PUBLIC int v4lconvert_vidioc_g_ctrl(struct 
> v4lconvert_data *data,
>               void *arg);
>  LIBV4L_PUBLIC int v4lconvert_vidioc_s_ctrl(struct v4lconvert_data *data,
>               void *arg);
> +LIBV4L_PUBLIC int v4lconvert_vidioc_g_ext_ctrls(struct v4lconvert_data *data,
> +             void *arg);
> +LIBV4L_PUBLIC int v4lconvert_vidioc_try_ext_ctrls(struct v4lconvert_data 
> *data,
> +             void *arg);
> +LIBV4L_PUBLIC int v4lconvert_vidioc_s_ext_ctrls(struct v4lconvert_data *data,
> +             void *arg);
>  
>  /* Is the passed in pixelformat supported as destination format? */
>  LIBV4L_PUBLIC int v4lconvert_supported_dst_format(unsigned int pixelformat);
> diff --git a/lib/libv4l2/libv4l2.c b/lib/libv4l2/libv4l2.c
> index 1dcf34d..8291ebe 100644
> --- a/lib/libv4l2/libv4l2.c
> +++ b/lib/libv4l2/libv4l2.c
> @@ -1022,6 +1022,9 @@ int v4l2_ioctl(int fd, unsigned long int request, ...)
>       case VIDIOC_QUERYCTRL:
>       case VIDIOC_G_CTRL:
>       case VIDIOC_S_CTRL:
> +     case VIDIOC_G_EXT_CTRLS:
> +     case VIDIOC_TRY_EXT_CTRLS:
> +     case VIDIOC_S_EXT_CTRLS:
>       case VIDIOC_ENUM_FRAMESIZES:
>       case VIDIOC_ENUM_FRAMEINTERVALS:
>               is_capture_request = 1;
> @@ -1129,6 +1132,18 @@ no_capture_request:
>               result = v4lconvert_vidioc_s_ctrl(devices[index].convert, arg);
>               break;
>  
> +     case VIDIOC_G_EXT_CTRLS:
> +             result = v4lconvert_vidioc_g_ext_ctrls(devices[index].convert, 
> arg);
> +             break;
> +
> +     case VIDIOC_TRY_EXT_CTRLS:
> +             result = 
> v4lconvert_vidioc_try_ext_ctrls(devices[index].convert, arg);
> +             break;
> +
> +     case VIDIOC_S_EXT_CTRLS:
> +             result = v4lconvert_vidioc_s_ext_ctrls(devices[index].convert, 
> arg);
> +             break;
> +
>       case VIDIOC_QUERYCAP: {
>               struct v4l2_capability *cap = arg;
>  
> diff --git a/lib/libv4lconvert/control/libv4lcontrol.c 
> b/lib/libv4lconvert/control/libv4lcontrol.c
> index ee39ba7..2fd585d 100644
> --- a/lib/libv4lconvert/control/libv4lcontrol.c
> +++ b/lib/libv4lconvert/control/libv4lcontrol.c
> @@ -916,6 +916,81 @@ int v4lcontrol_vidioc_g_ctrl(struct v4lcontrol_data 
> *data, void *arg)
>                       VIDIOC_G_CTRL, arg);
>  }
>  
> +static void v4lcontrol_alloc_valid_controls(struct v4lcontrol_data *data,
> +                     const struct v4l2_ext_controls *src,
> +                     struct v4l2_ext_controls *dst)
> +{
> +     struct v4l2_ext_control *ctrl;
> +     unsigned i, j;
> +
> +     *dst = *src;
> +     if (data->controls == 0)
> +             return;
> +     ctrl = malloc(src->count * sizeof(*ctrl));
> +     if (ctrl == NULL)
> +             return;
> +     dst->controls = ctrl;
> +     dst->count = 0;
> +     for (i = 0; i < src->count; i++) {
> +             for (j = 0; j < V4LCONTROL_COUNT; j++)
> +                     if ((data->controls & (1 << j)) &&
> +                         src->controls[i].id == fake_controls[j].id)
> +                             break;
> +             if (j == V4LCONTROL_COUNT)
> +                     ctrl[dst->count++] = src->controls[i];
> +     }
> +}
> +
> +static void v4lcontrol_free_valid_controls(struct v4lcontrol_data *data,
> +                     struct v4l2_ext_controls *src,
> +                     struct v4l2_ext_controls *dst)
> +{
> +     unsigned i, j, k = 0;
> +     int inc_idx;
> +
> +     src->error_idx = dst->error_idx;
> +     if (dst->controls == src->controls)
> +             return;
> +
> +     inc_idx = dst->error_idx < dst->count;
> +     for (i = 0; i < src->count; i++) {
> +             for (j = 0; j < V4LCONTROL_COUNT; j++)
> +                     if ((data->controls & (1 << j)) &&
> +                         src->controls[i].id == fake_controls[j].id)
> +                             break;
> +             if (j == V4LCONTROL_COUNT)
> +                     src->controls[i] = dst->controls[k++];
> +             else if (inc_idx)
> +                     src->error_idx++;
> +     }
> +     free(dst->controls);
> +}
> +
> +int v4lcontrol_vidioc_g_ext_ctrls(struct v4lcontrol_data *data, void *arg)
> +{
> +     struct v4l2_ext_controls *ctrls = arg;
> +     struct v4l2_ext_controls dst;
> +     int i, j;
> +     int res;
> +
> +     v4lcontrol_alloc_valid_controls(data, ctrls, &dst);
> +     res = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
> +                     VIDIOC_G_EXT_CTRLS, &dst);
> +     v4lcontrol_free_valid_controls(data, ctrls, &dst);
> +     if (res)
> +             return res;
> +
> +     for (i = 0; i < ctrls->count; i++) {
> +             for (j = 0; j < V4LCONTROL_COUNT; j++)
> +                     if ((data->controls & (1 << j)) &&
> +                         ctrls->controls[i].id == fake_controls[j].id) {
> +                             ctrls->controls[i].value = data->shm_values[j];
> +                             break;
> +                     }
> +     }
> +     return 0;
> +}
> +
>  int v4lcontrol_vidioc_s_ctrl(struct v4lcontrol_data *data, void *arg)
>  {
>       int i;
> @@ -938,6 +1013,72 @@ int v4lcontrol_vidioc_s_ctrl(struct v4lcontrol_data 
> *data, void *arg)
>                       VIDIOC_S_CTRL, arg);
>  }
>  
> +static int v4lcontrol_validate_ext_ctrls(struct v4lcontrol_data *data,
> +             struct v4l2_ext_controls *ctrls)
> +{
> +     int i, j;
> +
> +     if (data->controls == 0)
> +             return 0;
> +     for (i = 0; i < ctrls->count; i++) {
> +             for (j = 0; j < V4LCONTROL_COUNT; j++)
> +                     if ((data->controls & (1 << j)) &&
> +                         ctrls->controls[i].id == fake_controls[j].id) {
> +                             if (ctrls->controls[i].value > 
> fake_controls[j].maximum ||
> +                                 ctrls->controls[i].value < 
> fake_controls[j].minimum) {
> +                                     ctrls->error_idx = i;
> +                                     errno = EINVAL;
> +                                     return -1;
> +                             }
> +                     }
> +     }
> +     return 0;
> +}
> +
> +int v4lcontrol_vidioc_try_ext_ctrls(struct v4lcontrol_data *data, void *arg)
> +{
> +     struct v4l2_ext_controls *ctrls = arg;
> +     struct v4l2_ext_controls dst;
> +     int res = v4lcontrol_validate_ext_ctrls(data, ctrls);
> +
> +     if (res)
> +             return res;
> +
> +     v4lcontrol_alloc_valid_controls(data, ctrls, &dst);
> +     res = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
> +                     VIDIOC_TRY_EXT_CTRLS, &dst);
> +     v4lcontrol_free_valid_controls(data, ctrls, &dst);
> +     return res;
> +}
> +
> +int v4lcontrol_vidioc_s_ext_ctrls(struct v4lcontrol_data *data, void *arg)
> +{
> +     struct v4l2_ext_controls *ctrls = arg;
> +     struct v4l2_ext_controls dst;
> +     int i, j;
> +     int res = v4lcontrol_validate_ext_ctrls(data, ctrls);
> +
> +     if (res)
> +             return res;
> +
> +     v4lcontrol_alloc_valid_controls(data, ctrls, &dst);
> +     res = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
> +                     VIDIOC_S_EXT_CTRLS, &dst);
> +     v4lcontrol_free_valid_controls(data, ctrls, &dst);
> +     if (res)
> +             return res;
> +
> +     for (i = 0; i < ctrls->count; i++) {
> +             for (j = 0; j < V4LCONTROL_COUNT; j++)
> +                     if ((data->controls & (1 << j)) &&
> +                         ctrls->controls[i].id == fake_controls[j].id) {
> +                             data->shm_values[j] = ctrls->controls[i].value;
> +                             break;
> +                     }
> +     }
> +     return 0;
> +}
> +
>  int v4lcontrol_get_bandwidth(struct v4lcontrol_data *data)
>  {
>       return data->bandwidth;
> diff --git a/lib/libv4lconvert/control/libv4lcontrol.h 
> b/lib/libv4lconvert/control/libv4lcontrol.h
> index 804f1c5..fa9cf42 100644
> --- a/lib/libv4lconvert/control/libv4lcontrol.h
> +++ b/lib/libv4lconvert/control/libv4lcontrol.h
> @@ -72,5 +72,8 @@ int v4lcontrol_needs_conversion(struct v4lcontrol_data 
> *data);
>  int v4lcontrol_vidioc_queryctrl(struct v4lcontrol_data *data, void *arg);
>  int v4lcontrol_vidioc_g_ctrl(struct v4lcontrol_data *data, void *arg);
>  int v4lcontrol_vidioc_s_ctrl(struct v4lcontrol_data *data, void *arg);
> +int v4lcontrol_vidioc_g_ext_ctrls(struct v4lcontrol_data *data, void *arg);
> +int v4lcontrol_vidioc_try_ext_ctrls(struct v4lcontrol_data *data, void *arg);
> +int v4lcontrol_vidioc_s_ext_ctrls(struct v4lcontrol_data *data, void *arg);
>  
>  #endif
> diff --git a/lib/libv4lconvert/libv4lconvert.c 
> b/lib/libv4lconvert/libv4lconvert.c
> index acb8085..7ee7c19 100644
> --- a/lib/libv4lconvert/libv4lconvert.c
> +++ b/lib/libv4lconvert/libv4lconvert.c
> @@ -1659,6 +1659,21 @@ int v4lconvert_vidioc_s_ctrl(struct v4lconvert_data 
> *data, void *arg)
>       return v4lcontrol_vidioc_s_ctrl(data->control, arg);
>  }
>  
> +int v4lconvert_vidioc_g_ext_ctrls(struct v4lconvert_data *data, void *arg)
> +{
> +     return v4lcontrol_vidioc_g_ext_ctrls(data->control, arg);
> +}
> +
> +int v4lconvert_vidioc_try_ext_ctrls(struct v4lconvert_data *data, void *arg)
> +{
> +     return v4lcontrol_vidioc_try_ext_ctrls(data->control, arg);
> +}
> +
> +int v4lconvert_vidioc_s_ext_ctrls(struct v4lconvert_data *data, void *arg)
> +{
> +     return v4lcontrol_vidioc_s_ext_ctrls(data->control, arg);
> +}
> +
>  int v4lconvert_get_fps(struct v4lconvert_data *data)
>  {
>       return data->fps;
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to