diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1 index e50592cae2..25dea92ef5 100644 --- a/DOCS/man/en/mplayer.1 +++ b/DOCS/man/en/mplayer.1 @@ -1854,6 +1854,11 @@ These options set parameters of the mixer on the video capture card. They will have no effect, if your card does not have one. For v4l2 50 maps to the default value of the control, as reported by the driver. +.IPs "gain=<0\-100> (v4l2)" +Set gain control for video devices (usually webcams) to the desired +value and switch off automatic control. +A value of 0 enables automatic control. +If this option is omitted, gain control will not be modified. .IPs immediatemode= A value of 0 means capture and buffer audio and video together (default for MEncoder). diff --git a/cfg-common.h b/cfg-common.h index 42af04810f..00d2163097 100644 --- a/cfg-common.h +++ b/cfg-common.h @@ -436,6 +436,7 @@ m_option_t tvopts_conf[]={ {"contrast", &stream_tv_defaults.contrast, CONF_TYPE_INT, CONF_RANGE, -100, 100, NULL}, {"hue", &stream_tv_defaults.hue, CONF_TYPE_INT, CONF_RANGE, -100, 100, NULL}, {"saturation", &stream_tv_defaults.saturation, CONF_TYPE_INT, CONF_RANGE, -100, 100, NULL}, + {"gain", &stream_tv_defaults.gain, CONF_TYPE_INT, CONF_RANGE, -1, 100, NULL}, #if defined(HAVE_TV_V4L) || defined(HAVE_TV_V4L2) {"amode", &stream_tv_defaults.amode, CONF_TYPE_INT, CONF_RANGE, 0, 3, NULL}, {"volume", &stream_tv_defaults.volume, CONF_TYPE_INT, CONF_RANGE, 0, 65535, NULL}, diff --git a/stream/stream_tv.c b/stream/stream_tv.c index 4b3af7be7c..95ba0b97a7 100644 --- a/stream/stream_tv.c +++ b/stream/stream_tv.c @@ -72,6 +72,7 @@ tv_param_t stream_tv_defaults = { 0, //contrast 0, //hue 0, //saturation + -1, //gain NULL, //tdevice 0, //tformat 100, //tpage diff --git a/stream/tv.c b/stream/tv.c index be06149b1e..3315905930 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -759,6 +759,10 @@ no_audio: tv_set_color_options(tvh, TV_COLOR_SATURATION, tvh->tv_param->saturation); tv_set_color_options(tvh, TV_COLOR_CONTRAST, tvh->tv_param->contrast); + if(tvh->tv_param->gain!=-1) + if(funcs->control(tvh->priv,TVI_CONTROL_VID_SET_GAIN,&tvh->tv_param->gain)!=TVI_CONTROL_TRUE) + mp_msg(MSGT_TV,MSGL_WARN,"Unable to set gain control!\n"); + funcs->control(tvh->priv,TV_VBI_CONTROL_RESET,tvh->tv_param); return demuxer; diff --git a/stream/tv.h b/stream/tv.h index 5e67ef96f6..ff04a901d3 100644 --- a/stream/tv.h +++ b/stream/tv.h @@ -47,6 +47,7 @@ typedef struct tv_param_s { int contrast; int hue; int saturation; + int gain; char *tdevice; ///< teletext device int tformat; ///< teletext display format int tpage; ///< start teletext page @@ -151,6 +152,8 @@ typedef struct { #define TVI_CONTROL_VID_SET_CONTRAST 0x11c #define TVI_CONTROL_VID_GET_PICTURE 0x11d #define TVI_CONTROL_VID_SET_PICTURE 0x11e +#define TVI_CONTROL_VID_SET_GAIN 0x11f +#define TVI_CONTROL_VID_GET_GAIN 0x120 /* TUNER controls */ #define TVI_CONTROL_TUN_GET_FREQ 0x201 diff --git a/stream/tvi_v4l2.c b/stream/tvi_v4l2.c index d0d58cbd38..e049d940dd 100644 --- a/stream/tvi_v4l2.c +++ b/stream/tvi_v4l2.c @@ -478,7 +478,6 @@ static int set_mute(priv_t *priv, int value) */ static int set_control(priv_t *priv, struct v4l2_control *control, int val_signed) { struct v4l2_queryctrl qctrl; - qctrl.id = control->id; if (ioctl(priv->video_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query control failed: %s\n", @@ -806,6 +805,40 @@ static int control(priv_t *priv, int cmd, void *arg) control.id = V4L2_CID_SATURATION; control.value = *(int *)arg; return set_control(priv, &control, 1); + case TVI_CONTROL_VID_GET_GAIN: + { + + control.id = V4L2_CID_AUTOGAIN; + if(get_control(priv,&control,0)!=TVI_CONTROL_TRUE) + return TVI_CONTROL_FALSE; + + if(control.value){ //Auto Gain control is enabled + *(int*)arg=0; + return TVI_CONTROL_TRUE; + } + + //Manual Gain control + control.id = V4L2_CID_GAIN; + if(get_control(priv,&control,0)!=TVI_CONTROL_TRUE) + return TVI_CONTROL_FALSE; + + *(int*)arg=control.value?control.value:1; + + return TVI_CONTROL_TRUE; + } + case TVI_CONTROL_VID_SET_GAIN: + { + //value==0 means automatic gain control + int value=*(int*)arg; + + if (value < 0 || value>100) + return TVI_CONTROL_FALSE; + + control.id=value?V4L2_CID_GAIN:V4L2_CID_AUTOGAIN; + control.value=value?value:1; + + return set_control(priv,&control,0); + } case TVI_CONTROL_VID_GET_CONTRAST: control.id = V4L2_CID_CONTRAST; if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {