media: vivid: drop overlay support
Destructive overlay support (i.e. where the video frame is DMA-ed straight into a framebuffer) is effectively dead. It was a necessary evil in the early days when computers were not fast enough to copy SDTV video frames around, but today that's no longer a problem. It requires access to the framebuffer memory, which is a bad idea and very hard to do safely. In addition, in drm it is today almost impossible to get hold of the framebuffer address. So drop support for this. Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
parent
3c161e82df
commit
ccaa9d50ca
|
@ -126,7 +126,7 @@ MODULE_PARM_DESC(node_types, " node types, default is 0xe1d3d. Bitmask with the
|
|||
"\t\t bit 8: Video Output node\n"
|
||||
"\t\t bit 10-11: VBI Output node: 0 = none, 1 = raw vbi, 2 = sliced vbi, 3 = both\n"
|
||||
"\t\t bit 12: Radio Transmitter node\n"
|
||||
"\t\t bit 16: Framebuffer for testing overlays\n"
|
||||
"\t\t bit 16: Framebuffer for testing output overlays\n"
|
||||
"\t\t bit 17: Metadata Capture node\n"
|
||||
"\t\t bit 18: Metadata Output node\n"
|
||||
"\t\t bit 19: Touch Capture node\n");
|
||||
|
@ -326,7 +326,7 @@ static int vidioc_overlay(struct file *file, void *fh, unsigned i)
|
|||
struct video_device *vdev = video_devdata(file);
|
||||
|
||||
if (vdev->vfl_dir == VFL_DIR_RX)
|
||||
return vivid_vid_cap_overlay(file, fh, i);
|
||||
return -ENOTTY;
|
||||
return vivid_vid_out_overlay(file, fh, i);
|
||||
}
|
||||
|
||||
|
@ -335,38 +335,16 @@ static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a
|
|||
struct video_device *vdev = video_devdata(file);
|
||||
|
||||
if (vdev->vfl_dir == VFL_DIR_RX)
|
||||
return vivid_vid_cap_g_fbuf(file, fh, a);
|
||||
return -ENOTTY;
|
||||
return vivid_vid_out_g_fbuf(file, fh, a);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only support the framebuffer of one of the vivid instances.
|
||||
* Anything else is rejected.
|
||||
*/
|
||||
bool vivid_validate_fb(const struct v4l2_framebuffer *a)
|
||||
{
|
||||
struct vivid_dev *dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_devs; i++) {
|
||||
dev = vivid_devs[i];
|
||||
if (!dev || !dev->video_pbase)
|
||||
continue;
|
||||
if ((unsigned long)a->base == dev->video_pbase &&
|
||||
a->fmt.width <= dev->display_width &&
|
||||
a->fmt.height <= dev->display_height &&
|
||||
a->fmt.bytesperline <= dev->display_byte_stride)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a)
|
||||
{
|
||||
struct video_device *vdev = video_devdata(file);
|
||||
|
||||
if (vdev->vfl_dir == VFL_DIR_RX)
|
||||
return vivid_vid_cap_s_fbuf(file, fh, a);
|
||||
return -ENOTTY;
|
||||
return vivid_vid_out_s_fbuf(file, fh, a);
|
||||
}
|
||||
|
||||
|
@ -651,8 +629,6 @@ static int vivid_fop_release(struct file *file)
|
|||
vivid_reconnect(dev);
|
||||
}
|
||||
mutex_unlock(&dev->mutex);
|
||||
if (file->private_data == dev->overlay_cap_owner)
|
||||
dev->overlay_cap_owner = NULL;
|
||||
if (file->private_data == dev->radio_rx_rds_owner) {
|
||||
dev->radio_rx_rds_last_block = 0;
|
||||
dev->radio_rx_rds_owner = NULL;
|
||||
|
@ -778,10 +754,6 @@ static const struct v4l2_ioctl_ops vivid_ioctl_ops = {
|
|||
.vidioc_g_parm = vidioc_g_parm,
|
||||
.vidioc_s_parm = vidioc_s_parm,
|
||||
|
||||
.vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay,
|
||||
.vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay,
|
||||
.vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay,
|
||||
.vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay,
|
||||
.vidioc_g_fmt_vid_out_overlay = vidioc_g_fmt_vid_out_overlay,
|
||||
.vidioc_try_fmt_vid_out_overlay = vidioc_try_fmt_vid_out_overlay,
|
||||
.vidioc_s_fmt_vid_out_overlay = vidioc_s_fmt_vid_out_overlay,
|
||||
|
@ -862,7 +834,6 @@ static void vivid_dev_release(struct v4l2_device *v4l2_dev)
|
|||
vfree(dev->scaled_line);
|
||||
vfree(dev->blended_line);
|
||||
vfree(dev->edid);
|
||||
vfree(dev->bitmap_cap);
|
||||
vfree(dev->bitmap_out);
|
||||
tpg_free(&dev->tpg);
|
||||
kfree(dev->query_dv_timings_qmenu);
|
||||
|
@ -1107,7 +1078,7 @@ static void vivid_set_capabilities(struct vivid_dev *dev)
|
|||
/* set up the capabilities of the video capture device */
|
||||
dev->vid_cap_caps = dev->multiplanar ?
|
||||
V4L2_CAP_VIDEO_CAPTURE_MPLANE :
|
||||
V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY;
|
||||
V4L2_CAP_VIDEO_CAPTURE;
|
||||
dev->vid_cap_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
|
||||
if (dev->has_audio_inputs)
|
||||
dev->vid_cap_caps |= V4L2_CAP_AUDIO;
|
||||
|
@ -1396,7 +1367,7 @@ static int vivid_create_queues(struct vivid_dev *dev)
|
|||
}
|
||||
|
||||
if (dev->has_fb) {
|
||||
/* Create framebuffer for testing capture/output overlay */
|
||||
/* Create framebuffer for testing output overlay */
|
||||
ret = vivid_fb_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -1892,13 +1863,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
|
|||
vivid_update_format_cap(dev, false);
|
||||
vivid_update_format_out(dev);
|
||||
|
||||
/* initialize overlay */
|
||||
dev->fb_cap.fmt.width = dev->src_rect.width;
|
||||
dev->fb_cap.fmt.height = dev->src_rect.height;
|
||||
dev->fb_cap.fmt.pixelformat = dev->fmt_cap->fourcc;
|
||||
dev->fb_cap.fmt.bytesperline = dev->src_rect.width * tpg_g_twopixelsize(&dev->tpg, 0) / 2;
|
||||
dev->fb_cap.fmt.sizeimage = dev->src_rect.height * dev->fb_cap.fmt.bytesperline;
|
||||
|
||||
/* update touch configuration */
|
||||
dev->timeperframe_tch_cap.numerator = 1;
|
||||
dev->timeperframe_tch_cap.denominator = 10;
|
||||
|
|
|
@ -345,17 +345,6 @@ struct vivid_dev {
|
|||
|
||||
u32 power_present;
|
||||
|
||||
/* Capture Overlay */
|
||||
struct v4l2_framebuffer fb_cap;
|
||||
struct v4l2_fh *overlay_cap_owner;
|
||||
void *fb_vbase_cap;
|
||||
int overlay_cap_top, overlay_cap_left;
|
||||
enum v4l2_field overlay_cap_field;
|
||||
void *bitmap_cap;
|
||||
struct v4l2_clip clips_cap[MAX_CLIPS];
|
||||
struct v4l2_clip try_clips_cap[MAX_CLIPS];
|
||||
unsigned clipcount_cap;
|
||||
|
||||
/* Output */
|
||||
unsigned output;
|
||||
v4l2_std_id std_out;
|
||||
|
@ -613,6 +602,4 @@ static inline bool vivid_is_hdmi_out(const struct vivid_dev *dev)
|
|||
return dev->output_type[dev->output] == HDMI;
|
||||
}
|
||||
|
||||
bool vivid_validate_fb(const struct v4l2_framebuffer *a);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -554,109 +554,6 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if this pixel coordinate is a valid video pixel.
|
||||
*/
|
||||
static bool valid_pix(struct vivid_dev *dev, int win_y, int win_x, int fb_y, int fb_x)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dev->bitmap_cap) {
|
||||
/*
|
||||
* Only if the corresponding bit in the bitmap is set can
|
||||
* the video pixel be shown. Coordinates are relative to
|
||||
* the overlay window set by VIDIOC_S_FMT.
|
||||
*/
|
||||
const u8 *p = dev->bitmap_cap;
|
||||
unsigned stride = (dev->compose_cap.width + 7) / 8;
|
||||
|
||||
if (!(p[stride * win_y + win_x / 8] & (1 << (win_x & 7))))
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->clipcount_cap; i++) {
|
||||
/*
|
||||
* Only if the framebuffer coordinate is not in any of the
|
||||
* clip rectangles will be video pixel be shown.
|
||||
*/
|
||||
struct v4l2_rect *r = &dev->clips_cap[i].c;
|
||||
|
||||
if (fb_y >= r->top && fb_y < r->top + r->height &&
|
||||
fb_x >= r->left && fb_x < r->left + r->width)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw the image into the overlay buffer.
|
||||
* Note that the combination of overlay and multiplanar is not supported.
|
||||
*/
|
||||
static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf)
|
||||
{
|
||||
struct tpg_data *tpg = &dev->tpg;
|
||||
unsigned pixsize = tpg_g_twopixelsize(tpg, 0) / 2;
|
||||
void *vbase = dev->fb_vbase_cap;
|
||||
void *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
|
||||
unsigned img_width = dev->compose_cap.width;
|
||||
unsigned img_height = dev->compose_cap.height;
|
||||
unsigned stride = tpg->bytesperline[0];
|
||||
/* if quick is true, then valid_pix() doesn't have to be called */
|
||||
bool quick = dev->bitmap_cap == NULL && dev->clipcount_cap == 0;
|
||||
int x, y, w, out_x = 0;
|
||||
|
||||
/*
|
||||
* Overlay support is only supported for formats that have a twopixelsize
|
||||
* that's >= 2. Warn and bail out if that's not the case.
|
||||
*/
|
||||
if (WARN_ON(pixsize == 0))
|
||||
return;
|
||||
if ((dev->overlay_cap_field == V4L2_FIELD_TOP ||
|
||||
dev->overlay_cap_field == V4L2_FIELD_BOTTOM) &&
|
||||
dev->overlay_cap_field != buf->vb.field)
|
||||
return;
|
||||
|
||||
vbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride;
|
||||
x = dev->overlay_cap_left;
|
||||
w = img_width;
|
||||
if (x < 0) {
|
||||
out_x = -x;
|
||||
w = w - out_x;
|
||||
x = 0;
|
||||
} else {
|
||||
w = dev->fb_cap.fmt.width - x;
|
||||
if (w > img_width)
|
||||
w = img_width;
|
||||
}
|
||||
if (w <= 0)
|
||||
return;
|
||||
if (dev->overlay_cap_top >= 0)
|
||||
vbase += dev->overlay_cap_top * dev->fb_cap.fmt.bytesperline;
|
||||
for (y = dev->overlay_cap_top;
|
||||
y < dev->overlay_cap_top + (int)img_height;
|
||||
y++, vbuf += stride) {
|
||||
int px;
|
||||
|
||||
if (y < 0 || y > dev->fb_cap.fmt.height)
|
||||
continue;
|
||||
if (quick) {
|
||||
memcpy(vbase + x * pixsize,
|
||||
vbuf + out_x * pixsize, w * pixsize);
|
||||
vbase += dev->fb_cap.fmt.bytesperline;
|
||||
continue;
|
||||
}
|
||||
for (px = 0; px < w; px++) {
|
||||
if (!valid_pix(dev, y - dev->overlay_cap_top,
|
||||
px + out_x, y, px + x))
|
||||
continue;
|
||||
memcpy(vbase + (px + x) * pixsize,
|
||||
vbuf + (px + out_x) * pixsize,
|
||||
pixsize);
|
||||
}
|
||||
vbase += dev->fb_cap.fmt.bytesperline;
|
||||
}
|
||||
}
|
||||
|
||||
static void vivid_cap_update_frame_period(struct vivid_dev *dev)
|
||||
{
|
||||
u64 f_period;
|
||||
|
@ -730,11 +627,6 @@ static noinline_for_stack void vivid_thread_vid_cap_tick(struct vivid_dev *dev,
|
|||
dprintk(dev, 1, "filled buffer %d\n",
|
||||
vid_cap_buf->vb.vb2_buf.index);
|
||||
|
||||
/* Handle overlay */
|
||||
if (dev->overlay_cap_owner && dev->fb_cap.base &&
|
||||
dev->fb_cap.fmt.pixelformat == dev->fmt_cap->fourcc)
|
||||
vivid_overlay(dev, vid_cap_buf);
|
||||
|
||||
v4l2_ctrl_request_complete(vid_cap_buf->vb.vb2_buf.req_obj.req,
|
||||
&dev->ctrl_hdl_vid_cap);
|
||||
vb2_buffer_done(&vid_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
|
||||
|
|
|
@ -21,30 +21,6 @@
|
|||
#include "vivid-kthread-cap.h"
|
||||
#include "vivid-vid-cap.h"
|
||||
|
||||
static const struct vivid_fmt formats_ovl[] = {
|
||||
{
|
||||
.fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
|
||||
.vdownsampling = { 1 },
|
||||
.bit_depth = { 16 },
|
||||
.planes = 1,
|
||||
.buffers = 1,
|
||||
},
|
||||
{
|
||||
.fourcc = V4L2_PIX_FMT_XRGB555, /* gggbbbbb arrrrrgg */
|
||||
.vdownsampling = { 1 },
|
||||
.bit_depth = { 16 },
|
||||
.planes = 1,
|
||||
.buffers = 1,
|
||||
},
|
||||
{
|
||||
.fourcc = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
|
||||
.vdownsampling = { 1 },
|
||||
.bit_depth = { 16 },
|
||||
.planes = 1,
|
||||
.buffers = 1,
|
||||
},
|
||||
};
|
||||
|
||||
/* The number of discrete webcam framesizes */
|
||||
#define VIVID_WEBCAM_SIZES 6
|
||||
/* The number of discrete webcam frameintervals */
|
||||
|
@ -447,18 +423,10 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
|
|||
tpg_s_rgb_range(&dev->tpg, v4l2_ctrl_g_ctrl(dev->rgb_range_cap));
|
||||
break;
|
||||
}
|
||||
vfree(dev->bitmap_cap);
|
||||
dev->bitmap_cap = NULL;
|
||||
vivid_update_quality(dev);
|
||||
tpg_reset_source(&dev->tpg, dev->src_rect.width, dev->src_rect.height, dev->field_cap);
|
||||
dev->crop_cap = dev->src_rect;
|
||||
dev->crop_bounds_cap = dev->src_rect;
|
||||
if (dev->bitmap_cap &&
|
||||
(dev->compose_cap.width != dev->crop_cap.width ||
|
||||
dev->compose_cap.height != dev->crop_cap.height)) {
|
||||
vfree(dev->bitmap_cap);
|
||||
dev->bitmap_cap = NULL;
|
||||
}
|
||||
dev->compose_cap = dev->crop_cap;
|
||||
if (V4L2_FIELD_HAS_T_OR_B(dev->field_cap))
|
||||
dev->compose_cap.height /= 2;
|
||||
|
@ -701,11 +669,6 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (dev->overlay_cap_owner && dev->fb_cap.fmt.pixelformat != mp->pixelformat) {
|
||||
dprintk(dev, 1, "overlay is active, can't change pixelformat\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dev->fmt_cap = vivid_get_format(dev, mp->pixelformat);
|
||||
if (V4L2_FIELD_HAS_T_OR_B(mp->field))
|
||||
factor = 2;
|
||||
|
@ -927,8 +890,6 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
|
|||
struct vivid_dev *dev = video_drvdata(file);
|
||||
struct v4l2_rect *crop = &dev->crop_cap;
|
||||
struct v4l2_rect *compose = &dev->compose_cap;
|
||||
unsigned orig_compose_w = compose->width;
|
||||
unsigned orig_compose_h = compose->height;
|
||||
unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
|
||||
int ret;
|
||||
|
||||
|
@ -1052,11 +1013,6 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dev->bitmap_cap && (compose->width != orig_compose_w ||
|
||||
compose->height != orig_compose_h)) {
|
||||
vfree(dev->bitmap_cap);
|
||||
dev->bitmap_cap = NULL;
|
||||
}
|
||||
tpg_s_crop_compose(&dev->tpg, crop, compose);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1084,234 +1040,6 @@ int vivid_vid_cap_g_pixelaspect(struct file *file, void *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv,
|
||||
struct v4l2_fmtdesc *f)
|
||||
{
|
||||
struct vivid_dev *dev = video_drvdata(file);
|
||||
const struct vivid_fmt *fmt;
|
||||
|
||||
if (dev->multiplanar)
|
||||
return -ENOTTY;
|
||||
|
||||
if (f->index >= ARRAY_SIZE(formats_ovl))
|
||||
return -EINVAL;
|
||||
|
||||
fmt = &formats_ovl[f->index];
|
||||
|
||||
f->pixelformat = fmt->fourcc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vidioc_g_fmt_vid_overlay(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct vivid_dev *dev = video_drvdata(file);
|
||||
const struct v4l2_rect *compose = &dev->compose_cap;
|
||||
struct v4l2_window *win = &f->fmt.win;
|
||||
unsigned clipcount = win->clipcount;
|
||||
|
||||
if (dev->multiplanar)
|
||||
return -ENOTTY;
|
||||
|
||||
win->w.top = dev->overlay_cap_top;
|
||||
win->w.left = dev->overlay_cap_left;
|
||||
win->w.width = compose->width;
|
||||
win->w.height = compose->height;
|
||||
win->field = dev->overlay_cap_field;
|
||||
win->clipcount = dev->clipcount_cap;
|
||||
if (clipcount > dev->clipcount_cap)
|
||||
clipcount = dev->clipcount_cap;
|
||||
if (dev->bitmap_cap == NULL)
|
||||
win->bitmap = NULL;
|
||||
else if (win->bitmap) {
|
||||
if (copy_to_user(win->bitmap, dev->bitmap_cap,
|
||||
((compose->width + 7) / 8) * compose->height))
|
||||
return -EFAULT;
|
||||
}
|
||||
if (clipcount && win->clips)
|
||||
memcpy(win->clips, dev->clips_cap,
|
||||
clipcount * sizeof(dev->clips_cap[0]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vidioc_try_fmt_vid_overlay(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct vivid_dev *dev = video_drvdata(file);
|
||||
const struct v4l2_rect *compose = &dev->compose_cap;
|
||||
struct v4l2_window *win = &f->fmt.win;
|
||||
int i, j;
|
||||
|
||||
if (dev->multiplanar)
|
||||
return -ENOTTY;
|
||||
|
||||
win->w.left = clamp_t(int, win->w.left,
|
||||
-dev->fb_cap.fmt.width, dev->fb_cap.fmt.width);
|
||||
win->w.top = clamp_t(int, win->w.top,
|
||||
-dev->fb_cap.fmt.height, dev->fb_cap.fmt.height);
|
||||
win->w.width = compose->width;
|
||||
win->w.height = compose->height;
|
||||
if (win->field != V4L2_FIELD_BOTTOM && win->field != V4L2_FIELD_TOP)
|
||||
win->field = V4L2_FIELD_ANY;
|
||||
win->chromakey = 0;
|
||||
win->global_alpha = 0;
|
||||
if (win->clipcount && !win->clips)
|
||||
win->clipcount = 0;
|
||||
if (win->clipcount > MAX_CLIPS)
|
||||
win->clipcount = MAX_CLIPS;
|
||||
if (win->clipcount) {
|
||||
memcpy(dev->try_clips_cap, win->clips,
|
||||
win->clipcount * sizeof(dev->clips_cap[0]));
|
||||
for (i = 0; i < win->clipcount; i++) {
|
||||
struct v4l2_rect *r = &dev->try_clips_cap[i].c;
|
||||
|
||||
r->top = clamp_t(s32, r->top, 0, dev->fb_cap.fmt.height - 1);
|
||||
r->height = clamp_t(s32, r->height, 1, dev->fb_cap.fmt.height - r->top);
|
||||
r->left = clamp_t(u32, r->left, 0, dev->fb_cap.fmt.width - 1);
|
||||
r->width = clamp_t(u32, r->width, 1, dev->fb_cap.fmt.width - r->left);
|
||||
}
|
||||
/*
|
||||
* Yeah, so sue me, it's an O(n^2) algorithm. But n is a small
|
||||
* number and it's typically a one-time deal.
|
||||
*/
|
||||
for (i = 0; i < win->clipcount - 1; i++) {
|
||||
struct v4l2_rect *r1 = &dev->try_clips_cap[i].c;
|
||||
|
||||
for (j = i + 1; j < win->clipcount; j++) {
|
||||
struct v4l2_rect *r2 = &dev->try_clips_cap[j].c;
|
||||
|
||||
if (v4l2_rect_overlap(r1, r2))
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
memcpy(win->clips, dev->try_clips_cap,
|
||||
win->clipcount * sizeof(dev->clips_cap[0]));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vidioc_s_fmt_vid_overlay(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct vivid_dev *dev = video_drvdata(file);
|
||||
const struct v4l2_rect *compose = &dev->compose_cap;
|
||||
struct v4l2_window *win = &f->fmt.win;
|
||||
int ret = vidioc_try_fmt_vid_overlay(file, priv, f);
|
||||
unsigned bitmap_size = ((compose->width + 7) / 8) * compose->height;
|
||||
unsigned clips_size = win->clipcount * sizeof(dev->clips_cap[0]);
|
||||
void *new_bitmap = NULL;
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (win->bitmap) {
|
||||
new_bitmap = vzalloc(bitmap_size);
|
||||
|
||||
if (new_bitmap == NULL)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(new_bitmap, win->bitmap, bitmap_size)) {
|
||||
vfree(new_bitmap);
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
dev->overlay_cap_top = win->w.top;
|
||||
dev->overlay_cap_left = win->w.left;
|
||||
dev->overlay_cap_field = win->field;
|
||||
vfree(dev->bitmap_cap);
|
||||
dev->bitmap_cap = new_bitmap;
|
||||
dev->clipcount_cap = win->clipcount;
|
||||
if (dev->clipcount_cap)
|
||||
memcpy(dev->clips_cap, dev->try_clips_cap, clips_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vivid_vid_cap_overlay(struct file *file, void *fh, unsigned i)
|
||||
{
|
||||
struct vivid_dev *dev = video_drvdata(file);
|
||||
|
||||
if (dev->multiplanar)
|
||||
return -ENOTTY;
|
||||
|
||||
if (i && dev->fb_vbase_cap == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (i && dev->fb_cap.fmt.pixelformat != dev->fmt_cap->fourcc) {
|
||||
dprintk(dev, 1, "mismatch between overlay and video capture pixelformats\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dev->overlay_cap_owner && dev->overlay_cap_owner != fh)
|
||||
return -EBUSY;
|
||||
dev->overlay_cap_owner = i ? fh : NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vivid_vid_cap_g_fbuf(struct file *file, void *fh,
|
||||
struct v4l2_framebuffer *a)
|
||||
{
|
||||
struct vivid_dev *dev = video_drvdata(file);
|
||||
|
||||
if (dev->multiplanar)
|
||||
return -ENOTTY;
|
||||
|
||||
*a = dev->fb_cap;
|
||||
a->capability = V4L2_FBUF_CAP_BITMAP_CLIPPING |
|
||||
V4L2_FBUF_CAP_LIST_CLIPPING;
|
||||
a->flags = V4L2_FBUF_FLAG_PRIMARY;
|
||||
a->fmt.field = V4L2_FIELD_NONE;
|
||||
a->fmt.colorspace = V4L2_COLORSPACE_SRGB;
|
||||
a->fmt.priv = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vivid_vid_cap_s_fbuf(struct file *file, void *fh,
|
||||
const struct v4l2_framebuffer *a)
|
||||
{
|
||||
struct vivid_dev *dev = video_drvdata(file);
|
||||
const struct vivid_fmt *fmt;
|
||||
|
||||
if (dev->multiplanar)
|
||||
return -ENOTTY;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
|
||||
return -EPERM;
|
||||
|
||||
if (dev->overlay_cap_owner)
|
||||
return -EBUSY;
|
||||
|
||||
if (a->base == NULL) {
|
||||
dev->fb_cap.base = NULL;
|
||||
dev->fb_vbase_cap = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a->fmt.width < 48 || a->fmt.height < 32)
|
||||
return -EINVAL;
|
||||
fmt = vivid_get_format(dev, a->fmt.pixelformat);
|
||||
if (!fmt || !fmt->can_do_overlay)
|
||||
return -EINVAL;
|
||||
if (a->fmt.bytesperline < (a->fmt.width * fmt->bit_depth[0]) / 8)
|
||||
return -EINVAL;
|
||||
if (a->fmt.bytesperline > a->fmt.sizeimage / a->fmt.height)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Only support the framebuffer of one of the vivid instances.
|
||||
* Anything else is rejected.
|
||||
*/
|
||||
if (!vivid_validate_fb(a))
|
||||
return -EINVAL;
|
||||
|
||||
dev->fb_vbase_cap = phys_to_virt((unsigned long)a->base);
|
||||
dev->fb_cap = *a;
|
||||
dev->overlay_cap_left = clamp_t(int, dev->overlay_cap_left,
|
||||
-dev->fb_cap.fmt.width, dev->fb_cap.fmt.width);
|
||||
dev->overlay_cap_top = clamp_t(int, dev->overlay_cap_top,
|
||||
-dev->fb_cap.fmt.height, dev->fb_cap.fmt.height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct v4l2_audio vivid_audio_inputs[] = {
|
||||
{ 0, "TV", V4L2_AUDCAP_STEREO },
|
||||
{ 1, "Line-In", V4L2_AUDCAP_STEREO },
|
||||
|
|
|
@ -33,9 +33,6 @@ int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_fmtd
|
|||
int vidioc_g_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format *f);
|
||||
int vidioc_try_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format *f);
|
||||
int vidioc_s_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format *f);
|
||||
int vivid_vid_cap_overlay(struct file *file, void *fh, unsigned i);
|
||||
int vivid_vid_cap_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a);
|
||||
int vivid_vid_cap_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a);
|
||||
int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *inp);
|
||||
int vidioc_g_input(struct file *file, void *priv, unsigned *i);
|
||||
int vidioc_s_input(struct file *file, void *priv, unsigned i);
|
||||
|
|
Loading…
Reference in New Issue