Commit 88ab075a authored by Ian Armstrong's avatar Ian Armstrong Committed by Mauro Carvalho Chehab

V4L/DVB (7243): ivtv: yuv framebuffer tracking

The existing yuv code limits output to the display area occupied by the
framebuffer. This patch allows the yuv output to be 'detached' via
V4L2_FBUF_FLAG_OVERLAY.

By default, the yuv output window will be restricted to the framebuffer
dimensions and the output position is relative to the top left corner of the
framebuffer. This matches the behaviour of previous versions.

If V4L2_FBUF_FLAG_OVERLAY is cleared, the yuv output will no longer be linked
to the framebuffer. The maximum dimensions are either 720x576 or 720x480
depending on the current broadcast standard, with the output position
relative to the top left corner of the display. The framebuffer itself can be
resized, moved and panned without affecting the yuv output.
Signed-off-by: default avatarIan Armstrong <ian@iarmst.demon.co.uk>
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 520ebe5f
...@@ -711,6 +711,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) ...@@ -711,6 +711,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
itv->yuv_info.lace_mode = ivtv_yuv_mode; itv->yuv_info.lace_mode = ivtv_yuv_mode;
itv->yuv_info.lace_threshold = ivtv_yuv_threshold; itv->yuv_info.lace_threshold = ivtv_yuv_threshold;
itv->yuv_info.max_frames_buffered = 3; itv->yuv_info.max_frames_buffered = 3;
itv->yuv_info.track_osd = 1;
return 0; return 0;
} }
......
...@@ -456,6 +456,8 @@ struct yuv_playback_info ...@@ -456,6 +456,8 @@ struct yuv_playback_info
int v_filter_2; int v_filter_2;
int h_filter; int h_filter;
u8 track_osd; /* Should yuv output track the OSD size & position */
u32 osd_x_offset; u32 osd_x_offset;
u32 osd_y_offset; u32 osd_y_offset;
......
...@@ -712,6 +712,7 @@ static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg) ...@@ -712,6 +712,7 @@ static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg) int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg)
{ {
struct ivtv_open_id *id = NULL; struct ivtv_open_id *id = NULL;
struct yuv_playback_info *yi = &itv->yuv_info;
u32 data[CX2341X_MBOX_MAX_DATA]; u32 data[CX2341X_MBOX_MAX_DATA];
int streamtype = 0; int streamtype = 0;
...@@ -837,8 +838,14 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void ...@@ -837,8 +838,14 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
} else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
cropcap->bounds.width = itv->yuv_info.osd_full_w; if (yi->track_osd) {
cropcap->bounds.height = itv->yuv_info.osd_full_h; cropcap->bounds.width = yi->osd_full_w;
cropcap->bounds.height = yi->osd_full_h;
} else {
cropcap->bounds.width = 720;
cropcap->bounds.height =
itv->is_out_50hz ? 576 : 480;
}
cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
} else { } else {
...@@ -856,7 +863,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void ...@@ -856,7 +863,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
itv->yuv_info.main_rect = crop->c; yi->main_rect = crop->c;
return 0; return 0;
} else { } else {
if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
...@@ -878,7 +885,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void ...@@ -878,7 +885,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
crop->c = itv->yuv_info.main_rect; crop->c = yi->main_rect;
else else
crop->c = itv->main_rect; crop->c = itv->main_rect;
return 0; return 0;
...@@ -1070,11 +1077,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void ...@@ -1070,11 +1077,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
itv->main_rect.height = itv->params.height; itv->main_rect.height = itv->params.height;
ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
720, itv->main_rect.height, 0, 0); 720, itv->main_rect.height, 0, 0);
itv->yuv_info.main_rect = itv->main_rect; yi->main_rect = itv->main_rect;
if (!itv->osd_info) { if (!itv->osd_info) {
itv->yuv_info.osd_full_w = 720; yi->osd_full_w = 720;
itv->yuv_info.osd_full_h = yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
itv->is_out_50hz ? 576 : 480;
} }
} }
break; break;
...@@ -1272,6 +1278,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void ...@@ -1272,6 +1278,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
else else
fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
} }
if (yi->track_osd)
fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
break; break;
} }
...@@ -1285,6 +1293,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void ...@@ -1285,6 +1293,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
(fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0; (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
ivtv_set_osd_alpha(itv); ivtv_set_osd_alpha(itv);
yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
break; break;
} }
......
...@@ -718,9 +718,11 @@ static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f) ...@@ -718,9 +718,11 @@ static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
f->src_w -= (osd_scale * osd_crop) >> 16; f->src_w -= (osd_scale * osd_crop) >> 16;
} }
if (itv->yuv_info.track_osd) {
/* The OSD can be moved. Track to it */ /* The OSD can be moved. Track to it */
f->dst_x += itv->yuv_info.osd_x_offset; f->dst_x += itv->yuv_info.osd_x_offset;
f->dst_y += itv->yuv_info.osd_y_offset; f->dst_y += itv->yuv_info.osd_y_offset;
}
/* Width & height for both src & dst must be even. /* Width & height for both src & dst must be even.
Same for coordinates. */ Same for coordinates. */
...@@ -792,11 +794,19 @@ void ivtv_yuv_work_handler(struct ivtv *itv) ...@@ -792,11 +794,19 @@ void ivtv_yuv_work_handler(struct ivtv *itv)
IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame); IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
f = yi->new_frame_info[frame]; f = yi->new_frame_info[frame];
/* Update the osd pan info */ if (yi->track_osd) {
/* Snapshot the osd pan info */
f.pan_x = yi->osd_x_pan; f.pan_x = yi->osd_x_pan;
f.pan_y = yi->osd_y_pan; f.pan_y = yi->osd_y_pan;
f.vis_w = yi->osd_vis_w; f.vis_w = yi->osd_vis_w;
f.vis_h = yi->osd_vis_h; f.vis_h = yi->osd_vis_h;
} else {
/* Not tracking the osd, so assume full screen */
f.pan_x = 0;
f.pan_y = 0;
f.vis_w = 720;
f.vis_h = yi->decode_height;
}
/* Calculate the display window coordinates. Exit if nothing left */ /* Calculate the display window coordinates. Exit if nothing left */
if (!(yuv_update = ivtv_yuv_window_setup(itv, &f))) if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))
...@@ -965,12 +975,6 @@ static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args) ...@@ -965,12 +975,6 @@ static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
/* Are we going to offset the Y plane */ /* Are we going to offset the Y plane */
nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0; nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
/* Snapshot the osd pan info */
nf->pan_x = yi->osd_x_pan;
nf->pan_y = yi->osd_y_pan;
nf->vis_w = yi->osd_vis_w;
nf->vis_h = yi->osd_vis_h;
nf->update = 0; nf->update = 0;
nf->interlaced_y = 0; nf->interlaced_y = 0;
nf->interlaced_uv = 0; nf->interlaced_uv = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment