diff options
-rw-r--r-- | linux/drivers/media/video/cx18/cx18-cards.c | 2 | ||||
-rw-r--r-- | linux/drivers/media/video/cx18/cx18-ioctl.c | 6 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-cards.h | 2 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-ioctl.c | 41 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa6752hs.c | 127 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-empress.c | 25 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-i2c.c | 10 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-video.c | 42 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134.h | 3 | ||||
-rw-r--r-- | v4l2-apps/util/v4l2-ctl.cpp | 336 |
10 files changed, 418 insertions, 176 deletions
diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c index 8fe5f38c4..3cb9734ec 100644 --- a/linux/drivers/media/video/cx18/cx18-cards.c +++ b/linux/drivers/media/video/cx18/cx18-cards.c @@ -163,7 +163,7 @@ static const struct cx18_card cx18_card_h900 = { }, .audio_inputs = { { CX18_CARD_INPUT_AUD_TUNER, - CX18_AV_AUDIO8, 0 }, + CX18_AV_AUDIO5, 0 }, { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 0 }, }, diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index 1ef2690d4..b909c78d3 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -201,7 +201,6 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh, { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; - int w = fmt->fmt.pix.width; int h = fmt->fmt.pix.height; @@ -249,8 +248,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; int ret; - int w = fmt->fmt.pix.width; - int h = fmt->fmt.pix.height; + int w, h; ret = v4l2_prio_check(&cx->prio, &id->prio); if (ret) @@ -259,6 +257,8 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, ret = cx18_try_fmt_vid_cap(file, fh, fmt); if (ret) return ret; + w = fmt->fmt.pix.width; + h = fmt->fmt.pix.height; if (cx->params.width == w && cx->params.height == h) return 0; diff --git a/linux/drivers/media/video/ivtv/ivtv-cards.h b/linux/drivers/media/video/ivtv/ivtv-cards.h index 381af1bce..0b8fe85fb 100644 --- a/linux/drivers/media/video/ivtv/ivtv-cards.h +++ b/linux/drivers/media/video/ivtv/ivtv-cards.h @@ -154,7 +154,7 @@ #define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \ V4L2_CAP_SLICED_VBI_CAPTURE) -#define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \ +#define IVTV_CAP_DECODER (V4L2_CAP_VIDEO_OUTPUT | \ V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY) struct ivtv_card_video_input { diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index 61030309d..f00854ad6 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -101,18 +101,15 @@ void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) } } -static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) +static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) { int f, l; - u16 set = 0; for (f = 0; f < 2; f++) { for (l = 0; l < 24; l++) { fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal); - set |= fmt->service_lines[f][l]; } } - return set != 0; } u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt) @@ -474,7 +471,7 @@ static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format int h = fmt->fmt.pix.height; w = min(w, 720); - w = max(w, 1); + w = max(w, 2); h = min(h, itv->is_50hz ? 576 : 480); h = max(h, 2); ivtv_g_fmt_vid_cap(file, fh, fmt); @@ -512,27 +509,20 @@ static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_ static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) { struct ivtv_open_id *id = fh; - s32 w, h; - int field; - int ret; + struct ivtv *itv = id->itv; + s32 w = fmt->fmt.pix.width; + s32 h = fmt->fmt.pix.height; + int field = fmt->fmt.pix.field; + int ret = ivtv_g_fmt_vid_out(file, fh, fmt); - w = fmt->fmt.pix.width; - h = fmt->fmt.pix.height; - field = fmt->fmt.pix.field; - ret = ivtv_g_fmt_vid_out(file, fh, fmt); + w = min(w, 720); + w = max(w, 2); + h = min(h, itv->is_out_50hz ? 576 : 480); + h = max(h, 2); + if (id->type == IVTV_DEC_STREAM_TYPE_YUV) + fmt->fmt.pix.field = field; fmt->fmt.pix.width = w; fmt->fmt.pix.height = h; - if (!ret && id->type == IVTV_DEC_STREAM_TYPE_YUV) { - fmt->fmt.pix.field = field; - if (fmt->fmt.pix.width < 2) - fmt->fmt.pix.width = 2; - if (fmt->fmt.pix.width > 720) - fmt->fmt.pix.width = 720; - if (fmt->fmt.pix.height < 2) - fmt->fmt.pix.height = 2; - if (fmt->fmt.pix.height > 576) - fmt->fmt.pix.height = 576; - } return ret; } @@ -560,9 +550,9 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f struct ivtv_open_id *id = fh; struct ivtv *itv = id->itv; struct cx2341x_mpeg_params *p = &itv->params; + int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); int w = fmt->fmt.pix.width; int h = fmt->fmt.pix.height; - int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); if (ret) return ret; @@ -600,8 +590,7 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI) return ret; - if (check_service_set(vbifmt, itv->is_50hz) == 0) - return -EINVAL; + check_service_set(vbifmt, itv->is_50hz); if (atomic_read(&itv->capturing) > 0) return -EBUSY; itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); diff --git a/linux/drivers/media/video/saa7134/saa6752hs.c b/linux/drivers/media/video/saa7134/saa6752hs.c index 6c97d4ab4..8ccca4d56 100644 --- a/linux/drivers/media/video/saa7134/saa6752hs.c +++ b/linux/drivers/media/video/saa7134/saa6752hs.c @@ -225,7 +225,7 @@ static struct saa6752hs_mpeg_params param_defaults = /* ---------------------------------------------------------------------- */ -static int saa6752hs_chip_command(struct i2c_client* client, +static int saa6752hs_chip_command(struct i2c_client *client, enum saa6752hs_command command) { unsigned char buf[3]; @@ -292,54 +292,61 @@ static int saa6752hs_chip_command(struct i2c_client* client, } -static int saa6752hs_set_bitrate(struct i2c_client* client, +static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val) +{ + u8 buf[2]; + + buf[0] = reg; + buf[1] = val; + i2c_master_send(client, buf, 2); +} + +static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val) +{ + u8 buf[3]; + + buf[0] = reg; + buf[1] = val >> 8; + buf[2] = val & 0xff; + i2c_master_send(client, buf, 3); +} + +static int saa6752hs_set_bitrate(struct i2c_client *client, struct saa6752hs_state *h) { struct saa6752hs_mpeg_params *params = &h->params; - u8 buf[3]; int tot_bitrate; + int is_384k; /* set the bitrate mode */ - buf[0] = 0x71; - buf[1] = (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ? 0 : 1; - i2c_master_send(client, buf, 2); + set_reg8(client, 0x71, + params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); /* set the video bitrate */ if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { /* set the target bitrate */ - buf[0] = 0x80; - buf[1] = params->vi_bitrate >> 8; - buf[2] = params->vi_bitrate & 0xff; - i2c_master_send(client, buf, 3); + set_reg16(client, 0x80, params->vi_bitrate); /* set the max bitrate */ - buf[0] = 0x81; - buf[1] = params->vi_bitrate_peak >> 8; - buf[2] = params->vi_bitrate_peak & 0xff; - i2c_master_send(client, buf, 3); + set_reg16(client, 0x81, params->vi_bitrate_peak); tot_bitrate = params->vi_bitrate_peak; } else { /* set the target bitrate (no max bitrate for CBR) */ - buf[0] = 0x81; - buf[1] = params->vi_bitrate >> 8; - buf[2] = params->vi_bitrate & 0xff; - i2c_master_send(client, buf, 3); + set_reg16(client, 0x81, params->vi_bitrate); tot_bitrate = params->vi_bitrate; } /* set the audio encoding */ - buf[0] = 0x93; - buf[1] = (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3); - i2c_master_send(client, buf, 2); + set_reg8(client, 0x93, + params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3); /* set the audio bitrate */ - buf[0] = 0x94; if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) - buf[1] = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate; + is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate; else - buf[1] = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate; - tot_bitrate += buf[1] ? 384 : 256; - i2c_master_send(client, buf, 2); + is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate; + set_reg8(client, 0x94, is_384k); + tot_bitrate += is_384k ? 384 : 256; /* Note: the total max bitrate is determined by adding the video and audio bitrates together and also adding an extra 768kbit/s to stay on the @@ -350,16 +357,12 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX; /* set the total bitrate */ - buf[0] = 0xb1; - buf[1] = tot_bitrate >> 8; - buf[2] = tot_bitrate & 0xff; - i2c_master_send(client, buf, 3); - + set_reg16(client, 0xb1, tot_bitrate); return 0; } -static void saa6752hs_set_subsampling(struct i2c_client* client, - struct v4l2_format* f) +static void saa6752hs_set_subsampling(struct i2c_client *client, + struct v4l2_format *f) { struct saa6752hs_state *h = i2c_get_clientdata(client); int dist_352, dist_480, dist_720; @@ -666,51 +669,31 @@ static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) h = i2c_get_clientdata(client); /* Set video format - must be done first as it resets other settings */ - buf[0] = 0x41; - buf[1] = h->video_format; - i2c_master_send(client, buf, 2); + set_reg8(client, 0x41, h->video_format); /* Set number of lines in input signal */ - buf[0] = 0x40; - buf[1] = 0x00; - if (h->standard & V4L2_STD_525_60) - buf[1] = 0x01; - i2c_master_send(client, buf, 2); + set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0); /* set bitrate */ saa6752hs_set_bitrate(client, h); /* Set GOP structure {3, 13} */ - buf[0] = 0x72; - buf[1] = 0x03; - buf[2] = 0x0D; - i2c_master_send(client,buf,3); + set_reg16(client, 0x72, 0x030d); /* Set minimum Q-scale {4} */ - buf[0] = 0x82; - buf[1] = 0x04; - i2c_master_send(client,buf,2); + set_reg8(client, 0x82, 0x04); /* Set maximum Q-scale {12} */ - buf[0] = 0x83; - buf[1] = 0x0C; - i2c_master_send(client,buf,2); + set_reg8(client, 0x83, 0x0c); /* Set Output Protocol */ - buf[0] = 0xD0; - buf[1] = 0x81; - i2c_master_send(client,buf,2); + set_reg8(client, 0xd0, 0x81); /* Set video output stream format {TS} */ - buf[0] = 0xB0; - buf[1] = 0x05; - i2c_master_send(client,buf,2); + set_reg8(client, 0xb0, 0x05); /* Set leading null byte for TS */ - buf[0] = 0xF6; - buf[1] = (leading_null_bytes >> 8) & 0xff; - buf[2] = leading_null_bytes & 0xff; - i2c_master_send(client, buf, 3); + set_reg16(client, 0xf6, leading_null_bytes); /* compute PAT */ memcpy(localPAT, PAT, sizeof(PAT)); @@ -745,33 +728,21 @@ static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) localPMT[size - 1] = crc & 0xFF; /* Set Audio PID */ - buf[0] = 0xC1; - buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF; - buf[2] = h->params.ts_pid_audio & 0xFF; - i2c_master_send(client,buf,3); + set_reg16(client, 0xc1, h->params.ts_pid_audio); /* Set Video PID */ - buf[0] = 0xC0; - buf[1] = (h->params.ts_pid_video >> 8) & 0xFF; - buf[2] = h->params.ts_pid_video & 0xFF; - i2c_master_send(client,buf,3); + set_reg16(client, 0xc0, h->params.ts_pid_video); /* Set PCR PID */ - buf[0] = 0xC4; - buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF; - buf[2] = h->params.ts_pid_pcr & 0xFF; - i2c_master_send(client,buf,3); + set_reg16(client, 0xc4, h->params.ts_pid_pcr); /* Send SI tables */ i2c_master_send(client, localPAT, sizeof(PAT)); i2c_master_send(client, localPMT, size); /* mute then unmute audio. This removes buzzing artefacts */ - buf[0] = 0xa4; - buf[1] = 1; - i2c_master_send(client, buf, 2); - buf[1] = 0; - i2c_master_send(client, buf, 2); + set_reg8(client, 0xa4, 1); + set_reg8(client, 0xa4, 0); /* start it going */ saa6752hs_chip_command(client, SAA6752HS_COMMAND_START); diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c index 1451fdf99..9ebe166cc 100644 --- a/linux/drivers/media/video/saa7134/saa7134-empress.c +++ b/linux/drivers/media/video/saa7134/saa7134-empress.c @@ -303,15 +303,6 @@ static int empress_streamoff(struct file *file, void *priv, return videobuf_streamoff(&dev->empress_tsq); } -static int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, - unsigned int cmd, void *arg) -{ - if (dev->mpeg_i2c_client == NULL) - return -EINVAL; - return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client, - cmd, arg); -} - static int empress_s_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { @@ -431,6 +422,20 @@ static int empress_g_chip_ident(struct file *file, void *fh, return -EINVAL; } +static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct saa7134_dev *dev = file->private_data; + + return saa7134_s_std_internal(dev, NULL, id); +} + +static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct saa7134_dev *dev = file->private_data; + + *id = dev->tvnorm->id; + return 0; +} static const struct file_operations ts_fops = { @@ -465,6 +470,8 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { .vidioc_g_ctrl = empress_g_ctrl, .vidioc_s_ctrl = empress_s_ctrl, .vidioc_g_chip_ident = empress_g_chip_ident, + .vidioc_s_std = empress_s_std, + .vidioc_g_std = empress_g_std, }; /* ----------------------------------------------------------- */ diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c index bdec276e0..2ca03df8c 100644 --- a/linux/drivers/media/video/saa7134/saa7134-i2c.c +++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c @@ -432,6 +432,16 @@ void saa7134_i2c_call_clients(struct saa7134_dev *dev, i2c_clients_command(&dev->i2c_adap, cmd, arg); } +int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, + unsigned int cmd, void *arg) +{ + if (dev->mpeg_i2c_client == NULL) + return -EINVAL; + return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client, + cmd, arg); +} +EXPORT_SYMBOL_GPL(saa7134_i2c_call_saa6752); + int saa7134_i2c_register(struct saa7134_dev *dev) { dev->i2c_adap = saa7134_adap_template; diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index 547c0401a..241b60e3f 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -628,6 +628,9 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev) if (card_in(dev, dev->ctl_input).tv) saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); + /* Set the correct norm for the saa6752hs. This function + does nothing if there is no saa6752hs. */ + saa7134_i2c_call_saa6752(dev, VIDIOC_S_STD, &dev->tvnorm->id); } static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) @@ -1803,18 +1806,25 @@ static int saa7134_querycap(struct file *file, void *priv, return 0; } -static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) +int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id) { - struct saa7134_fh *fh = priv; - struct saa7134_dev *dev = fh->dev; unsigned long flags; unsigned int i; v4l2_std_id fixup; int err; - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + /* When called from the empress code fh == NULL. + That needs to be fixed somehow, but for now this is + good enough. */ + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } else if (res_locked(dev, RESOURCE_OVERLAY)) { + /* Don't change the std from the mpeg device + if overlay is active. */ + return -EBUSY; + } for (i = 0; i < TVNORMS; i++) if (*id == tvnorms[i].id) @@ -1847,7 +1857,7 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) *id = tvnorms[i].id; mutex_lock(&dev->lock); - if (res_check(fh, RESOURCE_OVERLAY)) { + if (fh && res_check(fh, RESOURCE_OVERLAY)) { spin_lock_irqsave(&dev->slock, flags); stop_preview(dev, fh); spin_unlock_irqrestore(&dev->slock, flags); @@ -1864,6 +1874,23 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) mutex_unlock(&dev->lock); return 0; } +EXPORT_SYMBOL_GPL(saa7134_s_std_internal); + +static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct saa7134_fh *fh = priv; + + return saa7134_s_std_internal(fh->dev, fh, id); +} + +static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct saa7134_fh *fh = priv; + struct saa7134_dev *dev = fh->dev; + + *id = dev->tvnorm->id; + return 0; +} static int saa7134_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap) @@ -2404,6 +2431,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_qbuf = saa7134_qbuf, .vidioc_dqbuf = saa7134_dqbuf, .vidioc_s_std = saa7134_s_std, + .vidioc_g_std = saa7134_g_std, .vidioc_enum_input = saa7134_enum_input, .vidioc_g_input = saa7134_g_input, .vidioc_s_input = saa7134_s_input, diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 55aa60f52..50319493d 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -667,6 +667,8 @@ int saa7134_i2c_register(struct saa7134_dev *dev); int saa7134_i2c_unregister(struct saa7134_dev *dev); void saa7134_i2c_call_clients(struct saa7134_dev *dev, unsigned int cmd, void *arg); +int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, + unsigned int cmd, void *arg); /* ----------------------------------------------------------- */ @@ -679,6 +681,7 @@ extern struct video_device saa7134_radio_template; int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c); +int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id); int saa7134_videoport_init(struct saa7134_dev *dev); void saa7134_set_tvnorm_hw(struct saa7134_dev *dev); diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp index 1c765cf96..417721c57 100644 --- a/v4l2-apps/util/v4l2-ctl.cpp +++ b/v4l2-apps/util/v4l2-ctl.cpp @@ -34,6 +34,7 @@ #include <errno.h> #include <sys/ioctl.h> #include <sys/time.h> +#include <dirent.h> #include <math.h> #include <sys/klog.h> @@ -43,6 +44,7 @@ #include <vector> #include <map> #include <string> +#include <algorithm> /* Short option list @@ -77,15 +79,25 @@ enum Option { OptSetVideoFormat = 'v', OptGetSlicedVbiOutFormat = 128, - OptSetSlicedVbiOutFormat, OptGetOverlayFormat, - //OptSetOverlayFormat, TODO OptGetOutputOverlayFormat, - OptSetOutputOverlayFormat, OptGetVbiFormat, - //OptSetVbiFormat, TODO OptGetVbiOutFormat, + OptGetVideoOutFormat, + OptSetSlicedVbiOutFormat, + OptSetOutputOverlayFormat, + OptSetOverlayFormat, + //OptSetVbiFormat, TODO //OptSetVbiOutFormat, TODO + OptSetVideoOutFormat, + OptTryVideoOutFormat, + OptTrySlicedVbiOutFormat, + OptTrySlicedVbiFormat, + OptTryVideoFormat, + OptTryOutputOverlayFormat, + OptTryOverlayFormat, + //OptTryVbiFormat, TODO + //OptTryVbiOutFormat, TODO OptAll, OptStreamOff, OptStreamOn, @@ -94,8 +106,6 @@ enum Option { OptLogStatus, OptVerbose, OptSilent, - OptGetVideoOutFormat, - OptSetVideoOutFormat, OptGetSlicedVbiCap, OptGetSlicedVbiOutCap, OptGetFBuf, @@ -119,12 +129,14 @@ enum Option { OptGetOverlayCropCap, OptGetOutputOverlayCropCap, OptOverlay, + OptListDevices, OptLast = 256 }; static char options[OptLast]; static int app_result; +static int verbose; static unsigned capabilities; @@ -143,6 +155,9 @@ static ctrl_get_list get_ctrls; typedef std::map<std::string,std::string> ctrl_set_map; static ctrl_set_map set_ctrls; +typedef std::vector<std::string> dev_vec; +typedef std::map<std::string, std::string> dev_map; + typedef struct { unsigned flag; const char *str; @@ -162,6 +177,9 @@ static const flag_def service_def[] = { #define FmtChromaKey (1L<<2) #define FmtGlobalAlpha (1L<<3) #define FmtPixelFormat (1L<<4) +#define FmtLeft (1L<<5) +#define FmtTop (1L<<6) +#define FmtField (1L<<7) /* crop specified */ #define CropWidth (1L<<0) @@ -176,8 +194,10 @@ static struct option long_options[] = { {"device", required_argument, 0, OptSetDevice}, {"get-fmt-video", no_argument, 0, OptGetVideoFormat}, {"set-fmt-video", required_argument, 0, OptSetVideoFormat}, + {"try-fmt-video", required_argument, 0, OptTryVideoFormat}, {"get-fmt-video-out", no_argument, 0, OptGetVideoOutFormat}, {"set-fmt-video-out", required_argument, 0, OptSetVideoOutFormat}, + {"try-fmt-video-out", required_argument, 0, OptTryVideoOutFormat}, {"help", no_argument, 0, OptHelp}, {"get-output", no_argument, 0, OptGetOutput}, {"set-output", required_argument, 0, OptSetOutput}, @@ -207,12 +227,17 @@ static struct option long_options[] = { {"verbose", no_argument, 0, OptVerbose}, {"log-status", no_argument, 0, OptLogStatus}, {"get-fmt-overlay", no_argument, 0, OptGetOverlayFormat}, + {"set-fmt-overlay", required_argument, 0, OptSetOverlayFormat}, + {"try-fmt-overlay", required_argument, 0, OptTryOverlayFormat}, {"get-fmt-output-overlay", no_argument, 0, OptGetOutputOverlayFormat}, {"set-fmt-output-overlay", required_argument, 0, OptSetOutputOverlayFormat}, + {"try-fmt-output-overlay", required_argument, 0, OptTryOutputOverlayFormat}, {"get-fmt-sliced-vbi", no_argument, 0, OptGetSlicedVbiFormat}, {"set-fmt-sliced-vbi", required_argument, 0, OptSetSlicedVbiFormat}, + {"try-fmt-sliced-vbi", required_argument, 0, OptTrySlicedVbiFormat}, {"get-fmt-sliced-vbi-out", no_argument, 0, OptGetSlicedVbiOutFormat}, {"set-fmt-sliced-vbi-out", required_argument, 0, OptSetSlicedVbiOutFormat}, + {"try-fmt-sliced-vbi-out", required_argument, 0, OptTrySlicedVbiOutFormat}, {"get-fmt-vbi", no_argument, 0, OptGetVbiFormat}, {"get-fmt-vbi-out", no_argument, 0, OptGetVbiOutFormat}, {"get-sliced-vbi-cap", no_argument, 0, OptGetSlicedVbiCap}, @@ -232,6 +257,7 @@ static struct option long_options[] = { {"get-crop-output-overlay", no_argument, 0, OptGetOutputOverlayCrop}, {"set-crop-output-overlay", required_argument, 0, OptSetOutputOverlayCrop}, {"overlay", required_argument, 0, OptOverlay}, + {"list-devices", no_argument, 0, OptListDevices}, {0, 0, 0, 0} }; @@ -240,16 +266,6 @@ static void usage(void) printf("Usage:\n"); printf("Common options:\n" " --all display all information available\n" - " -B, --get-fmt-sliced-vbi\n" - " query the sliced VBI capture format [VIDIOC_G_FMT]\n" - " -b, --set-fmt-sliced-vbi=<mode>\n" - " set the sliced VBI capture format to <mode> [VIDIOC_S_FMT]\n" - " <mode> is a comma separated list of:\n" - " off: turn off sliced VBI (cannot be combined with other modes)\n" - " teletext: teletext (PAL/SECAM)\n" - " cc: closed caption (NTSC)\n" - " wss: widescreen signal (PAL/SECAM)\n" - " vps: VPS (PAL/SECAM)\n" " -C, --get-ctrl=<ctrl>[,<ctrl>...]\n" " get the value of the controls [VIDIOC_G_EXT_CTRLS]\n" " -c, --set-ctrl=<ctrl>=<val>[,<ctrl>=<val>...]\n" @@ -292,27 +308,46 @@ static void usage(void) " set the video capture format [VIDIOC_S_FMT]\n" " pixelformat is either the format index as reported by\n" " --list-formats, or the fourcc value as a string\n" + " --list-devices list all v4l devices\n" " --silent only set the result code, do not print any messages\n" " --verbose turn on verbose ioctl status reporting\n" "\n"); printf("Uncommon options:\n" + " --try-fmt-video=width=<w>,height=<h>,pixelformat=<f>\n" + " try the video capture format [VIDIOC_TRY_FMT]\n" + " pixelformat is either the format index as reported by\n" + " --list-formats, or the fourcc value as a string\n" " --get-fmt-video-out\n" " query the video output format [VIDIOC_G_FMT]\n" " --set-fmt-video-out=width=<w>,height=<h>\n" " set the video output format [VIDIOC_S_FMT]\n" + " --try-fmt-video-out=width=<w>,height=<h>\n" + " try the video output format [VIDIOC_TRY_FMT]\n" " --get-fmt-overlay query the video overlay format [VIDIOC_G_FMT]\n" " --get-fmt-output-overlay\n" " query the video output overlay format [VIDIOC_G_FMT]\n" - " --set-fmt-output-overlay=chromakey=<key>,global_alpha=<alpha>\n" - " set the video output overlay format [VIDIOC_S_FMT]\n" + " --set-fmt-overlay\n" + " --try-fmt-overlay\n" + " --set-fmt-output-overlay\n" + " --try-fmt-output-overlay=chromakey=<key>,global_alpha=<alpha>,\n" + " top=<t>,left=<l>,width=<w>,height=<h>,field=<f>\n" + " set/try the video or video output overlay format [VIDIOC_TRY_FMT]\n" + " <f> can be one of:\n" + " any, none, top, bottom, interlaced, seq_tb, seq_bt, alternate,\n" + " interlaced_tb, interlaced_bt\n" " --get-sliced-vbi-cap\n" " query the sliced VBI capture capabilities [VIDIOC_G_SLICED_VBI_CAP]\n" " --get-sliced-vbi-out-cap\n" " query the sliced VBI output capabilities [VIDIOC_G_SLICED_VBI_CAP]\n" + " -B, --get-fmt-sliced-vbi\n" + " query the sliced VBI capture format [VIDIOC_G_FMT]\n" " --get-fmt-sliced-vbi-out\n" " query the sliced VBI output format [VIDIOC_G_FMT]\n" - " --set-fmt-sliced-vbi-out=<mode>\n" - " set the sliced VBI output format to <mode> [VIDIOC_S_FMT]\n" + " -b, --set-fmt-sliced-vbi\n" + " --try-fmt-sliced-vbi\n" + " --set-fmt-sliced-vbi-out\n" + " --try-fmt-sliced-vbi-out=<mode>\n" + " (try to) set the sliced VBI capture/output format to <mode> [VIDIOC_S/TRY_FMT]\n" " <mode> is a comma separated list of:\n" " off: turn off sliced VBI (cannot be combined with other modes)\n" " teletext: teletext (PAL/SECAM)\n" @@ -1021,12 +1056,91 @@ static int doioctl(int fd, int request, void *parm, const char *name) if (options[OptSilent]) return retVal; if (retVal < 0) printf("%s: failed: %s\n", name, strerror(errno)); - else if (options[OptVerbose]) + else if (verbose) printf("%s: ok\n", name); return retVal; } +static bool is_v4l_dev(const char *name) +{ + return !memcmp(name, "vtx", 3) || + !memcmp(name, "video", 5) || + !memcmp(name, "radio", 5) || + !memcmp(name, "vbi", 3); +} + +static int calc_node_val(const char *s) +{ + int n = 0; + + s = strrchr(s, '/') + 1; + if (!memcmp(s, "video", 5)) n = 0; + else if (!memcmp(s, "radio", 5)) n = 0x100; + else if (!memcmp(s, "vbi", 3)) n = 0x200; + else if (!memcmp(s, "vtx", 3)) n = 0x300; + n += atol(s + (n >= 0x200 ? 3 : 5)); + return n; +} + +static bool sort_on_device_name(const std::string &s1, const std::string &s2) +{ + int n1 = calc_node_val(s1.c_str()); + int n2 = calc_node_val(s2.c_str()); + + return n1 < n2; +} + +static void list_devices() +{ + DIR *dp; + struct dirent *ep; + dev_vec files; + dev_map cards; + struct v4l2_capability vcap; + + dp = opendir("/dev"); + if (dp == NULL) { + perror ("Couldn't open the directory"); + return; + } + while (ep = readdir(dp)) + if (is_v4l_dev(ep->d_name)) + files.push_back(std::string("/dev/") + ep->d_name); + closedir(dp); + +#if 0 + dp = opendir("/dev/v4l"); + if (dp) { + while (ep = readdir(dp)) + if (is_v4l_dev(ep->d_name)) + files.push_back(std::string("/dev/v4l/") + ep->d_name); + closedir(dp); + } +#endif + + std::sort(files.begin(), files.end(), sort_on_device_name); + + for (dev_vec::iterator iter = files.begin(); + iter != files.end(); ++iter) { + int fd = open(iter->c_str(), O_RDWR); + std::string bus_info; + + if (fd < 0) + continue; + doioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP"); + close(fd); + bus_info = (const char *)vcap.bus_info; + if (cards[bus_info].empty()) + cards[bus_info] += std::string((char *)vcap.card) + " (" + bus_info + "):\n"; + cards[bus_info] += "\t" + (*iter) + "\n"; + } + for (dev_map::iterator iter = cards.begin(); + iter != cards.end(); ++iter) { + printf("%s\n", iter->second.c_str()); + } +} + static int parse_subopt(char **subs, const char * const *subopts, char **value) { int opt = getsubopt(subs, (char * const *)subopts, value); @@ -1131,6 +1245,21 @@ static void parse_crop(char *optarg, unsigned int &set_crop, v4l2_rect &vcrop) } } +static enum v4l2_field parse_field(const char *s) +{ + if (!strcmp(s, "any")) return V4L2_FIELD_ANY; + if (!strcmp(s, "none")) return V4L2_FIELD_NONE; + if (!strcmp(s, "top")) return V4L2_FIELD_TOP; + if (!strcmp(s, "bottom")) return V4L2_FIELD_BOTTOM; + if (!strcmp(s, "interlaced")) return V4L2_FIELD_INTERLACED; + if (!strcmp(s, "seq_tb")) return V4L2_FIELD_SEQ_TB; + if (!strcmp(s, "seq_bt")) return V4L2_FIELD_SEQ_BT; + if (!strcmp(s, "alternate")) return V4L2_FIELD_ALTERNATE; + if (!strcmp(s, "interlaced_tb")) return V4L2_FIELD_INTERLACED_TB; + if (!strcmp(s, "interlaced_bt")) return V4L2_FIELD_INTERLACED_BT; + return V4L2_FIELD_ANY; +} + int main(int argc, char **argv) { char *value, *subs; @@ -1146,6 +1275,7 @@ int main(int argc, char **argv) unsigned int set_crop_overlay = 0; unsigned int set_crop_out_overlay = 0; unsigned int set_fbuf = 0; + unsigned int set_overlay_fmt = 0; unsigned int set_overlay_fmt_out = 0; int mode = V4L2_TUNER_MODE_STEREO; /* set audio mode */ @@ -1159,6 +1289,7 @@ int main(int argc, char **argv) struct v4l2_format vbi_fmt_out; /* set_format/get_format for sliced VBI output */ struct v4l2_format raw_fmt; /* set_format/get_format for VBI */ struct v4l2_format raw_fmt_out; /* set_format/get_format for VBI output */ + struct v4l2_format overlay_fmt; /* set_format/get_format video overlay */ struct v4l2_format overlay_fmt_out; /* set_format/get_format video overlay output */ struct v4l2_tuner tuner; /* set_tuner/get_tuner */ struct v4l2_capability vcap; /* list_cap */ @@ -1178,14 +1309,18 @@ int main(int argc, char **argv) struct v4l2_frequency vf; /* get_freq/set_freq */ struct v4l2_standard vs; /* list_std */ int overlay; /* overlay */ + unsigned int *set_overlay_fmt_ptr; + struct v4l2_format *overlay_fmt_ptr; char short_options[26 * 2 * 2 + 1]; int idx = 0; + int ret; memset(&vfmt, 0, sizeof(vfmt)); memset(&vbi_fmt, 0, sizeof(vbi_fmt)); memset(&raw_fmt, 0, sizeof(raw_fmt)); memset(&vfmt_out, 0, sizeof(vfmt_out)); memset(&vbi_fmt_out, 0, sizeof(vbi_fmt_out)); + memset(&overlay_fmt, 0, sizeof(overlay_fmt)); memset(&overlay_fmt_out, 0, sizeof(overlay_fmt_out)); memset(&raw_fmt_out, 0, sizeof(raw_fmt_out)); memset(&tuner, 0, sizeof(tuner)); @@ -1238,6 +1373,7 @@ int main(int argc, char **argv) } break; case OptSetVideoFormat: + case OptTryVideoFormat: subs = optarg; while (*subs != '\0') { static const char *const subopts[] = { @@ -1269,6 +1405,7 @@ int main(int argc, char **argv) } break; case OptSetVideoOutFormat: + case OptTryVideoOutFormat: subs = optarg; while (*subs != '\0') { static const char *const subopts[] = { @@ -1289,23 +1426,63 @@ int main(int argc, char **argv) } } break; + case OptSetOverlayFormat: + case OptTryOverlayFormat: case OptSetOutputOverlayFormat: + case OptTryOutputOverlayFormat: + switch (ch) { + case OptSetOverlayFormat: + case OptTryOverlayFormat: + set_overlay_fmt_ptr = &set_overlay_fmt; + overlay_fmt_ptr = &overlay_fmt; + break; + case OptSetOutputOverlayFormat: + case OptTryOutputOverlayFormat: + set_overlay_fmt_ptr = &set_overlay_fmt_out; + overlay_fmt_ptr = &overlay_fmt_out; + break; + } subs = optarg; while (*subs != '\0') { static const char *const subopts[] = { "chromakey", "global_alpha", + "left", + "top", + "width", + "height", + "field", NULL }; switch (parse_subopt(&subs, subopts, &value)) { case 0: - overlay_fmt_out.fmt.win.chromakey = strtol(value, 0L, 0); - set_overlay_fmt_out |= FmtChromaKey; + overlay_fmt_ptr->fmt.win.chromakey = strtol(value, 0L, 0); + *set_overlay_fmt_ptr |= FmtChromaKey; break; case 1: - overlay_fmt_out.fmt.win.global_alpha = strtol(value, 0L, 0); - set_overlay_fmt_out |= FmtGlobalAlpha; + overlay_fmt_ptr->fmt.win.global_alpha = strtol(value, 0L, 0); + *set_overlay_fmt_ptr |= FmtGlobalAlpha; + break; + case 2: + overlay_fmt_ptr->fmt.win.w.left = strtol(value, 0L, 0); + *set_overlay_fmt_ptr |= FmtLeft; + break; + case 3: + overlay_fmt_ptr->fmt.win.w.top = strtol(value, 0L, 0); + *set_overlay_fmt_ptr |= FmtTop; + break; + case 4: + overlay_fmt_ptr->fmt.win.w.width = strtol(value, 0L, 0); + *set_overlay_fmt_ptr |= FmtWidth; + break; + case 5: + overlay_fmt_ptr->fmt.win.w.height = strtol(value, 0L, 0); + *set_overlay_fmt_ptr |= FmtHeight; + break; + case 6: + overlay_fmt_ptr->fmt.win.field = parse_field(value); + *set_overlay_fmt_ptr |= FmtField; break; } } @@ -1439,11 +1616,13 @@ int main(int argc, char **argv) break; case OptSetSlicedVbiFormat: case OptSetSlicedVbiOutFormat: + case OptTrySlicedVbiFormat: + case OptTrySlicedVbiOutFormat: { bool foundOff = false; v4l2_format *fmt = &vbi_fmt; - if (ch == OptSetSlicedVbiOutFormat) + if (ch == OptSetSlicedVbiOutFormat || ch == OptTrySlicedVbiOutFormat) fmt = &vbi_fmt_out; fmt->fmt.sliced.service_set = 0; subs = optarg; @@ -1486,6 +1665,9 @@ int main(int argc, char **argv) } break; } + case OptListDevices: + list_devices(); + break; case ':': fprintf(stderr, "Option `%s' requires a value\n", argv[optind]); @@ -1513,6 +1695,7 @@ int main(int argc, char **argv) exit(1); } + verbose = options[OptVerbose]; doioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP"); capabilities = vcap.capabilities; find_controls(fd); @@ -1550,6 +1733,7 @@ int main(int argc, char **argv) options[OptGetFBuf] = 1; options[OptGetCropCap] = 1; options[OptGetOutputCropCap] = 1; + options[OptSilent] = 1; } /* Information Opts */ @@ -1632,7 +1816,7 @@ int main(int argc, char **argv) } } - if (options[OptSetVideoFormat]) { + if (options[OptSetVideoFormat] || options[OptTryVideoFormat]) { struct v4l2_format in_vfmt; in_vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1653,12 +1837,17 @@ int main(int argc, char **argv) in_vfmt.fmt.pix.pixelformat = fmt.pixelformat; } } - doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT"); + if (options[OptSetVideoFormat]) + ret = doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT"); + else + ret = doioctl(fd, VIDIOC_TRY_FMT, &in_vfmt, "VIDIOC_TRY_FMT"); + if (ret == 0 && verbose) + printfmt(in_vfmt); } } set_vid_fmt_error: - if (options[OptSetVideoOutFormat]) { + if (options[OptSetVideoOutFormat] || options[OptTryVideoOutFormat]) { struct v4l2_format in_vfmt; in_vfmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; @@ -1667,35 +1856,65 @@ set_vid_fmt_error: in_vfmt.fmt.pix.width = vfmt_out.fmt.pix.width; if (set_fmts_out & FmtHeight) in_vfmt.fmt.pix.height = vfmt_out.fmt.pix.height; - doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT"); + + if (options[OptSetVideoOutFormat]) + ret = doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT"); + else + ret = doioctl(fd, VIDIOC_TRY_FMT, &in_vfmt, "VIDIOC_TRY_FMT"); + if (ret == 0 && verbose) + printfmt(in_vfmt); } } - if (options[OptSetSlicedVbiFormat]) { - if (vbi_fmt.fmt.sliced.service_set == 0) { - // switch to raw mode - vbi_fmt.type = V4L2_BUF_TYPE_VBI_CAPTURE; - if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt, "VIDIOC_G_FMT") == 0) - doioctl(fd, VIDIOC_S_FMT, &vbi_fmt, "VIDIOC_S_FMT"); - } else { - vbi_fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - doioctl(fd, VIDIOC_S_FMT, &vbi_fmt, "VIDIOC_S_FMT"); - } + if (options[OptSetSlicedVbiFormat] || options[OptTrySlicedVbiFormat]) { + vbi_fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; + if (options[OptSetSlicedVbiFormat]) + ret = doioctl(fd, VIDIOC_S_FMT, &vbi_fmt, "VIDIOC_S_FMT"); + else + ret = doioctl(fd, VIDIOC_TRY_FMT, &vbi_fmt, "VIDIOC_TRY_FMT"); + if (ret == 0 && verbose) + printfmt(vbi_fmt); } - if (options[OptSetSlicedVbiOutFormat]) { - if (vbi_fmt_out.fmt.sliced.service_set == 0) { - // switch to raw mode - vbi_fmt_out.type = V4L2_BUF_TYPE_VBI_OUTPUT; - if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt_out, "VIDIOC_G_FMT") == 0) - doioctl(fd, VIDIOC_S_FMT, &vbi_fmt_out, "VIDIOC_S_FMT"); - } else { - vbi_fmt_out.type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT; - doioctl(fd, VIDIOC_S_FMT, &vbi_fmt_out, "VIDIOC_S_FMT"); + if (options[OptSetSlicedVbiOutFormat] || options[OptTrySlicedVbiOutFormat]) { + vbi_fmt_out.type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT; + if (options[OptSetSlicedVbiOutFormat]) + ret = doioctl(fd, VIDIOC_S_FMT, &vbi_fmt_out, "VIDIOC_S_FMT"); + else + ret = doioctl(fd, VIDIOC_TRY_FMT, &vbi_fmt_out, "VIDIOC_TRY_FMT"); + if (ret == 0 && verbose) + printfmt(vbi_fmt_out); + } + + if (options[OptSetOverlayFormat] || options[OptTryOverlayFormat]) { + struct v4l2_format fmt; + + fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + if (doioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT") == 0) { + if (set_overlay_fmt & FmtChromaKey) + fmt.fmt.win.chromakey = overlay_fmt.fmt.win.chromakey; + if (set_overlay_fmt & FmtGlobalAlpha) + fmt.fmt.win.global_alpha = overlay_fmt.fmt.win.global_alpha; + if (set_overlay_fmt & FmtLeft) + fmt.fmt.win.w.left = overlay_fmt.fmt.win.w.left; + if (set_overlay_fmt & FmtTop) + fmt.fmt.win.w.top = overlay_fmt.fmt.win.w.top; + if (set_overlay_fmt & FmtWidth) + fmt.fmt.win.w.width = overlay_fmt.fmt.win.w.width; + if (set_overlay_fmt & FmtHeight) + fmt.fmt.win.w.height = overlay_fmt.fmt.win.w.height; + if (set_overlay_fmt & FmtField) + fmt.fmt.win.field = overlay_fmt.fmt.win.field; + if (options[OptSetOverlayFormat]) + ret = doioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT"); + else + ret = doioctl(fd, VIDIOC_TRY_FMT, &fmt, "VIDIOC_TRY_FMT"); + if (ret == 0 && verbose) + printfmt(fmt); } } - if (options[OptSetOutputOverlayFormat]) { + if (options[OptSetOutputOverlayFormat] || options[OptTryOutputOverlayFormat]) { struct v4l2_format fmt; fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY; @@ -1704,7 +1923,22 @@ set_vid_fmt_error: fmt.fmt.win.chromakey = overlay_fmt_out.fmt.win.chromakey; if (set_overlay_fmt_out & FmtGlobalAlpha) fmt.fmt.win.global_alpha = overlay_fmt_out.fmt.win.global_alpha; - doioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT"); + if (set_overlay_fmt_out & FmtLeft) + fmt.fmt.win.w.left = overlay_fmt_out.fmt.win.w.left; + if (set_overlay_fmt_out & FmtTop) + fmt.fmt.win.w.top = overlay_fmt_out.fmt.win.w.top; + if (set_overlay_fmt_out & FmtWidth) + fmt.fmt.win.w.width = overlay_fmt_out.fmt.win.w.width; + if (set_overlay_fmt_out & FmtHeight) + fmt.fmt.win.w.height = overlay_fmt_out.fmt.win.w.height; + if (set_overlay_fmt_out & FmtField) + fmt.fmt.win.field = overlay_fmt_out.fmt.win.field; + if (options[OptSetOutputOverlayFormat]) + ret = doioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT"); + else + ret = doioctl(fd, VIDIOC_TRY_FMT, &fmt, "VIDIOC_TRY_FMT"); + if (ret == 0 && verbose) + printfmt(fmt); } } |