|
@@ -1549,11 +1549,32 @@ static long __video_do_ioctl(struct file *file,
|
|
|
{
|
|
|
struct v4l2_crop *p = arg;
|
|
|
|
|
|
- if (!ops->vidioc_g_crop)
|
|
|
+ if (!ops->vidioc_g_crop && !ops->vidioc_g_selection)
|
|
|
break;
|
|
|
|
|
|
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
|
|
|
- ret = ops->vidioc_g_crop(file, fh, p);
|
|
|
+
|
|
|
+ if (ops->vidioc_g_crop) {
|
|
|
+ ret = ops->vidioc_g_crop(file, fh, p);
|
|
|
+ } else {
|
|
|
+ /* simulate capture crop using selection api */
|
|
|
+ struct v4l2_selection s = {
|
|
|
+ .type = p->type,
|
|
|
+ };
|
|
|
+
|
|
|
+ /* crop means compose for output devices */
|
|
|
+ if (V4L2_TYPE_IS_OUTPUT(p->type))
|
|
|
+ s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
|
|
|
+ else
|
|
|
+ s.target = V4L2_SEL_TGT_CROP_ACTIVE;
|
|
|
+
|
|
|
+ ret = ops->vidioc_g_selection(file, fh, &s);
|
|
|
+
|
|
|
+ /* copying results to old structure on success */
|
|
|
+ if (!ret)
|
|
|
+ p->c = s.r;
|
|
|
+ }
|
|
|
+
|
|
|
if (!ret)
|
|
|
dbgrect(vfd, "", &p->c);
|
|
|
break;
|
|
@@ -1562,15 +1583,33 @@ static long __video_do_ioctl(struct file *file,
|
|
|
{
|
|
|
struct v4l2_crop *p = arg;
|
|
|
|
|
|
- if (!ops->vidioc_s_crop)
|
|
|
+ if (!ops->vidioc_s_crop && !ops->vidioc_s_selection)
|
|
|
break;
|
|
|
+
|
|
|
if (ret_prio) {
|
|
|
ret = ret_prio;
|
|
|
break;
|
|
|
}
|
|
|
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
|
|
|
dbgrect(vfd, "", &p->c);
|
|
|
- ret = ops->vidioc_s_crop(file, fh, p);
|
|
|
+
|
|
|
+ if (ops->vidioc_s_crop) {
|
|
|
+ ret = ops->vidioc_s_crop(file, fh, p);
|
|
|
+ } else {
|
|
|
+ /* simulate capture crop using selection api */
|
|
|
+ struct v4l2_selection s = {
|
|
|
+ .type = p->type,
|
|
|
+ .r = p->c,
|
|
|
+ };
|
|
|
+
|
|
|
+ /* crop means compose for output devices */
|
|
|
+ if (V4L2_TYPE_IS_OUTPUT(p->type))
|
|
|
+ s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
|
|
|
+ else
|
|
|
+ s.target = V4L2_SEL_TGT_CROP_ACTIVE;
|
|
|
+
|
|
|
+ ret = ops->vidioc_s_selection(file, fh, &s);
|
|
|
+ }
|
|
|
break;
|
|
|
}
|
|
|
case VIDIOC_G_SELECTION:
|
|
@@ -1610,11 +1649,42 @@ static long __video_do_ioctl(struct file *file,
|
|
|
struct v4l2_cropcap *p = arg;
|
|
|
|
|
|
/*FIXME: Should also show v4l2_fract pixelaspect */
|
|
|
- if (!ops->vidioc_cropcap)
|
|
|
+ if (!ops->vidioc_cropcap && !ops->vidioc_g_selection)
|
|
|
break;
|
|
|
|
|
|
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
|
|
|
- ret = ops->vidioc_cropcap(file, fh, p);
|
|
|
+ if (ops->vidioc_cropcap) {
|
|
|
+ ret = ops->vidioc_cropcap(file, fh, p);
|
|
|
+ } else {
|
|
|
+ struct v4l2_selection s = { .type = p->type };
|
|
|
+
|
|
|
+ /* obtaining bounds */
|
|
|
+ if (V4L2_TYPE_IS_OUTPUT(p->type))
|
|
|
+ s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
|
|
|
+ else
|
|
|
+ s.target = V4L2_SEL_TGT_CROP_BOUNDS;
|
|
|
+
|
|
|
+ ret = ops->vidioc_g_selection(file, fh, &s);
|
|
|
+ if (ret)
|
|
|
+ break;
|
|
|
+ p->bounds = s.r;
|
|
|
+
|
|
|
+ /* obtaining defrect */
|
|
|
+ if (V4L2_TYPE_IS_OUTPUT(p->type))
|
|
|
+ s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
|
|
|
+ else
|
|
|
+ s.target = V4L2_SEL_TGT_CROP_DEFAULT;
|
|
|
+
|
|
|
+ ret = ops->vidioc_g_selection(file, fh, &s);
|
|
|
+ if (ret)
|
|
|
+ break;
|
|
|
+ p->defrect = s.r;
|
|
|
+
|
|
|
+ /* setting trivial pixelaspect */
|
|
|
+ p->pixelaspect.numerator = 1;
|
|
|
+ p->pixelaspect.denominator = 1;
|
|
|
+ }
|
|
|
+
|
|
|
if (!ret) {
|
|
|
dbgrect(vfd, "bounds ", &p->bounds);
|
|
|
dbgrect(vfd, "defrect ", &p->defrect);
|