forked from luck/tmp_suning_uos_patched
V4L/DVB (8896): pvrusb2: Implement crop support
Implement pvrusb2 driver plumbing to support cropping. Submitted by a pvrusb2 user. Signed-off-by: Mike Isely <isely@pobox.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
fe15f13679
commit
e784bfb93c
@ -319,6 +319,7 @@ struct pvr2_hdw {
|
||||
struct pvr2_ctl_info std_info_cur;
|
||||
struct v4l2_standard *std_defs;
|
||||
const char **std_enum_names;
|
||||
struct v4l2_cropcap cropcap;
|
||||
|
||||
// Generated string names, one per actual V4L2 standard
|
||||
const char *std_mask_ptrs[32];
|
||||
@ -367,6 +368,10 @@ struct pvr2_hdw {
|
||||
VCREATE_DATA(bass);
|
||||
VCREATE_DATA(treble);
|
||||
VCREATE_DATA(mute);
|
||||
VCREATE_DATA(cropl);
|
||||
VCREATE_DATA(cropt);
|
||||
VCREATE_DATA(cropw);
|
||||
VCREATE_DATA(croph);
|
||||
VCREATE_DATA(input);
|
||||
VCREATE_DATA(audiomode);
|
||||
VCREATE_DATA(res_hor);
|
||||
|
@ -402,6 +402,52 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left)
|
||||
{
|
||||
struct v4l2_cropcap *cap = &cptr->hdw->cropcap;
|
||||
if (cap->bounds.width > 0) {
|
||||
/* This statement is present purely to shut up
|
||||
checkpatch.pl */
|
||||
*left = cap->bounds.left - cap->defrect.left;
|
||||
} else {
|
||||
/* This statement is present purely to shut up
|
||||
checkpatch.pl */
|
||||
*left = -119;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left)
|
||||
{
|
||||
struct v4l2_cropcap *cap = &cptr->hdw->cropcap;
|
||||
if (cap->bounds.width > 0) {
|
||||
*left = cap->bounds.left + cap->bounds.width
|
||||
- cap->defrect.left;
|
||||
*left += 3;
|
||||
*left -= cptr->hdw->cropw_val;
|
||||
} else {
|
||||
/* This statement is present purely to shut up
|
||||
checkpatch.pl */
|
||||
*left = 340;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top)
|
||||
{
|
||||
struct v4l2_cropcap *cap = &cptr->hdw->cropcap;
|
||||
if (cap->bounds.height > 0) {
|
||||
/* This statement is present purely to shut up
|
||||
checkpatch.pl */
|
||||
*top = cap->bounds.top - cap->defrect.top;
|
||||
} else {
|
||||
/* This statement is present purely to shut up
|
||||
checkpatch.pl */
|
||||
*top = -19;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
|
||||
{
|
||||
/* Actual maximum depends on the video standard in effect. */
|
||||
@ -413,6 +459,19 @@ static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top)
|
||||
{
|
||||
struct v4l2_cropcap *cap = &cptr->hdw->cropcap;
|
||||
if (cap->bounds.height > 0) {
|
||||
*top = cap->bounds.top + cap->bounds.height - cap->defrect.top;
|
||||
*top -= cptr->hdw->croph_val;
|
||||
} else {
|
||||
ctrl_vres_max_get(cptr, top);
|
||||
*top -= 32;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp)
|
||||
{
|
||||
/* Actual minimum depends on device digitizer type. */
|
||||
@ -779,6 +838,10 @@ VCREATE_FUNCS(balance)
|
||||
VCREATE_FUNCS(bass)
|
||||
VCREATE_FUNCS(treble)
|
||||
VCREATE_FUNCS(mute)
|
||||
VCREATE_FUNCS(cropl)
|
||||
VCREATE_FUNCS(cropt)
|
||||
VCREATE_FUNCS(cropw)
|
||||
VCREATE_FUNCS(croph)
|
||||
VCREATE_FUNCS(audiomode)
|
||||
VCREATE_FUNCS(res_hor)
|
||||
VCREATE_FUNCS(res_ver)
|
||||
@ -849,6 +912,39 @@ static const struct pvr2_ctl_info control_defs[] = {
|
||||
.default_value = 0,
|
||||
DEFREF(mute),
|
||||
DEFBOOL,
|
||||
}, {
|
||||
.desc = "Capture left margin",
|
||||
.name = "crop_left",
|
||||
.internal_id = PVR2_CID_CROPL,
|
||||
.default_value = 0,
|
||||
DEFREF(cropl),
|
||||
DEFINT(-129, 340),
|
||||
.get_min_value = ctrl_cropl_min_get,
|
||||
.get_max_value = ctrl_cropl_max_get,
|
||||
}, {
|
||||
.desc = "Capture top margin",
|
||||
.name = "crop_top",
|
||||
.internal_id = PVR2_CID_CROPT,
|
||||
.default_value = 0,
|
||||
DEFREF(cropt),
|
||||
DEFINT(-35, 544),
|
||||
.get_min_value = ctrl_cropt_min_get,
|
||||
.get_max_value = ctrl_cropt_max_get,
|
||||
}, {
|
||||
.desc = "Capture width",
|
||||
.name = "crop_width",
|
||||
.internal_id = PVR2_CID_CROPW,
|
||||
.default_value = 720,
|
||||
DEFREF(cropw),
|
||||
DEFINT(388, 849), /* determined empirically, any res_hor>=64 */
|
||||
}, {
|
||||
.desc = "Capture height",
|
||||
.name = "crop_height",
|
||||
.internal_id = PVR2_CID_CROPH,
|
||||
.default_value = 480,
|
||||
DEFREF(croph),
|
||||
DEFINT(32, 576),
|
||||
.get_max_value = ctrl_vres_max_get,
|
||||
},{
|
||||
.desc = "Video Source",
|
||||
.name = "input",
|
||||
@ -2092,6 +2188,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
|
||||
valid_std_mask;
|
||||
}
|
||||
|
||||
memset(&hdw->cropcap, 0, sizeof hdw->cropcap);
|
||||
hdw->eeprom_addr = -1;
|
||||
hdw->unit_number = -1;
|
||||
hdw->v4l_minor_number_video = -1;
|
||||
@ -2528,6 +2625,28 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
|
||||
/* Can't commit anything until pathway is ok. */
|
||||
return 0;
|
||||
}
|
||||
/* The broadcast decoder can only scale down, so if
|
||||
* res_*_dirty && crop window < output format ==> enlarge crop.
|
||||
*
|
||||
* The mpeg encoder receives fields of res_hor_val dots and
|
||||
* res_ver_val halflines. Limits: hor<=720, ver<=576.
|
||||
*/
|
||||
if (hdw->res_hor_dirty && hdw->cropw_val < hdw->res_hor_val) {
|
||||
hdw->cropw_val = hdw->res_hor_val;
|
||||
hdw->cropw_dirty = !0;
|
||||
} else if (hdw->cropw_dirty) {
|
||||
hdw->res_hor_dirty = !0; /* must rescale */
|
||||
hdw->res_hor_val = min(720, hdw->cropw_val);
|
||||
}
|
||||
if (hdw->res_ver_dirty && hdw->croph_val < hdw->res_ver_val) {
|
||||
hdw->croph_val = hdw->res_ver_val;
|
||||
hdw->croph_dirty = !0;
|
||||
} else if (hdw->croph_dirty) {
|
||||
int nvres = hdw->std_mask_cur & V4L2_STD_525_60 ? 480 : 576;
|
||||
hdw->res_ver_dirty = !0;
|
||||
hdw->res_ver_val = min(nvres, hdw->croph_val);
|
||||
}
|
||||
|
||||
/* If any of the below has changed, then we can't do the update
|
||||
while the pipeline is running. Pipeline must be paused first
|
||||
and decoder -> encoder connection be made quiescent before we
|
||||
|
@ -36,6 +36,10 @@
|
||||
#define PVR2_CID_FREQUENCY 6
|
||||
#define PVR2_CID_HRES 7
|
||||
#define PVR2_CID_VRES 8
|
||||
#define PVR2_CID_CROPL 9
|
||||
#define PVR2_CID_CROPT 10
|
||||
#define PVR2_CID_CROPW 11
|
||||
#define PVR2_CID_CROPH 12
|
||||
|
||||
/* Legal values for the INPUT state variable */
|
||||
#define PVR2_CVAL_INPUT_TV 0
|
||||
|
@ -37,8 +37,9 @@
|
||||
#define OP_VOLUME 3
|
||||
#define OP_FREQ 4
|
||||
#define OP_AUDIORATE 5
|
||||
#define OP_SIZE 6
|
||||
#define OP_LOG 7
|
||||
#define OP_CROP 6
|
||||
#define OP_SIZE 7
|
||||
#define OP_LOG 8
|
||||
|
||||
static const struct pvr2_i2c_op * const ops[] = {
|
||||
[OP_STANDARD] = &pvr2_i2c_op_v4l2_standard,
|
||||
@ -46,6 +47,7 @@ static const struct pvr2_i2c_op * const ops[] = {
|
||||
[OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh,
|
||||
[OP_VOLUME] = &pvr2_i2c_op_v4l2_volume,
|
||||
[OP_FREQ] = &pvr2_i2c_op_v4l2_frequency,
|
||||
[OP_CROP] = &pvr2_i2c_op_v4l2_crop,
|
||||
[OP_SIZE] = &pvr2_i2c_op_v4l2_size,
|
||||
[OP_LOG] = &pvr2_i2c_op_v4l2_log,
|
||||
};
|
||||
@ -59,6 +61,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
|
||||
(1 << OP_BCSH) |
|
||||
(1 << OP_VOLUME) |
|
||||
(1 << OP_FREQ) |
|
||||
(1 << OP_CROP) |
|
||||
(1 << OP_SIZE) |
|
||||
(1 << OP_LOG));
|
||||
cp->status_poll = pvr2_v4l2_cmd_status_poll;
|
||||
|
@ -233,6 +233,55 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = {
|
||||
};
|
||||
|
||||
|
||||
static void set_crop(struct pvr2_hdw *hdw)
|
||||
{
|
||||
struct v4l2_cropcap cap;
|
||||
struct v4l2_crop crop;
|
||||
int stat;
|
||||
|
||||
memset(&cap, 0, sizeof cap);
|
||||
cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
stat = pvr2_i2c_core_cmd(hdw, VIDIOC_CROPCAP, &cap);
|
||||
hdw->cropcap = cap;
|
||||
|
||||
memset(&crop, 0, sizeof crop);
|
||||
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
crop.c = cap.defrect;
|
||||
crop.c.left += hdw->cropl_val;
|
||||
crop.c.top += hdw->cropt_val;
|
||||
crop.c.height = hdw->croph_val;
|
||||
crop.c.width = hdw->cropw_val;
|
||||
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,
|
||||
"i2c v4l2 set_crop stat=%d cap=%d:%d:%d:%d"
|
||||
" crop=%d:%d:%d:%d", stat, cap.bounds.width,
|
||||
cap.bounds.height, cap.bounds.left, cap.bounds.top,
|
||||
crop.c.width, crop.c.height, crop.c.left, crop.c.top);
|
||||
|
||||
if (stat >= 0) {
|
||||
/* This comment is present purely to keep
|
||||
checkpatch.pl quiet */
|
||||
pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop);
|
||||
}
|
||||
}
|
||||
|
||||
static int check_crop(struct pvr2_hdw *hdw)
|
||||
{
|
||||
/* The "0 +" stupidity is present only to get checkpatch.pl to
|
||||
shut up. I _want_ those parantheses present so that the
|
||||
two lines automatically line up in my editor. I despise
|
||||
checkpatch.pl. */
|
||||
return 0 + (hdw->cropl_dirty || hdw->cropt_dirty ||
|
||||
hdw->cropw_dirty || hdw->croph_dirty);
|
||||
}
|
||||
|
||||
const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = {
|
||||
.check = check_crop,
|
||||
.update = set_crop,
|
||||
.name = "v4l2_crop",
|
||||
};
|
||||
|
||||
|
||||
static void do_log(struct pvr2_hdw *hdw)
|
||||
{
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()");
|
||||
|
@ -29,6 +29,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio;
|
||||
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh;
|
||||
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume;
|
||||
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency;
|
||||
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop;
|
||||
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size;
|
||||
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode;
|
||||
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log;
|
||||
|
Loading…
Reference in New Issue
Block a user