m_recordPrio = new QCheckBox(parentWidget());
addWidget(m_recordPrio);
- if (!isRadio() && !isVbi() && !m_isOutput && (has_crop() || has_compose())) {
+ if (!isRadio() && !isVbi() && (has_crop() || has_compose())) {
addTitle("Cropping & Compose Settings");
cropSection();
}
void GeneralTab::outputChanged(int output)
{
s_output((__u32)output);
+
+ if (m_audioOutput)
+ updateAudioOutput();
+
updateVideoOutput();
updateVidOutFormat();
updateGUIOutput(output);
void GeneralTab::cropChanged()
{
- v4l2_crop crop;
+ v4l2_selection sel;
- if (!m_cropWidth->isEnabled())
+ if (!m_cropWidth->isEnabled() || !cur_io_has_crop())
return;
- crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- crop.c.width = m_cropWidth->value();
- crop.c.left = m_cropLeft->value();
- crop.c.height = m_cropHeight->value();
- crop.c.top = m_cropTop->value();
- cv4l_ioctl(VIDIOC_S_CROP, &crop);
- updateVidCapFormat();
+ sel.type = g_selection_type();
+ sel.target = V4L2_SEL_TGT_CROP;
+ sel.r.width = m_cropWidth->value();
+ sel.r.left = m_cropLeft->value();
+ sel.r.height = m_cropHeight->value();
+ sel.r.top = m_cropTop->value();
+ s_selection(sel);
+ updateVidFormat();
}
void GeneralTab::composeChanged()
{
v4l2_selection sel;
- if (!m_composeWidth->isEnabled() || !input_has_compose())
+ if (!m_composeWidth->isEnabled() || !cur_io_has_compose())
return;
- sel.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ sel.type = g_selection_type();
sel.target = V4L2_SEL_TGT_COMPOSE;
sel.r.width = m_composeWidth->value();
sel.r.left = m_composeLeft->value();
sel.r.height = m_composeHeight->value();
sel.r.top = m_composeTop->value();
- cv4l_ioctl(VIDIOC_S_SELECTION, &sel);
- updateVidCapFormat();
+ s_selection(sel);
+ updateVidFormat();
}
void GeneralTab::updateVideoInput()
if (m_audioInput)
m_audioInput->setEnabled(in.audioset);
if (m_cropWidth) {
- bool has_crop = input_has_crop();
+ bool has_crop = cur_io_has_crop();
m_cropWidth->setEnabled(has_crop);
m_cropLeft->setEnabled(has_crop);
m_cropTop->setEnabled(has_crop);
}
if (m_composeWidth) {
- bool has_compose = input_has_compose();
+ bool has_compose = cur_io_has_compose();
m_composeWidth->setEnabled(has_compose);
m_composeLeft->setEnabled(has_compose);
updateTimings();
m_videoTimings->setEnabled(out.capabilities & V4L2_OUT_CAP_DV_TIMINGS);
}
+ if (m_audioOutput)
+ m_audioOutput->setEnabled(out.audioset);
+ if (m_cropWidth) {
+ bool has_crop = cur_io_has_crop();
+
+ m_cropWidth->setEnabled(has_crop);
+ m_cropLeft->setEnabled(has_crop);
+ m_cropHeight->setEnabled(has_crop);
+ m_cropTop->setEnabled(has_crop);
+ }
+ if (m_composeWidth) {
+ bool has_compose = cur_io_has_compose();
+
+ m_composeWidth->setEnabled(has_compose);
+ m_composeLeft->setEnabled(has_compose);
+ m_composeHeight->setEnabled(has_compose);
+ m_composeTop->setEnabled(has_compose);
+ }
g_mw->updateLimRGBRange();
}
return;
m_vidOutFormats->setCurrentIndex(desc.index);
updateVidFields();
+ updateCrop();
+ updateCompose();
}
void GeneralTab::updateVidFields()
if (m_cropWidth == NULL || !m_cropWidth->isEnabled())
return;
- v4l2_cropcap cropcap;
- v4l2_rect &b = cropcap.bounds;
- v4l2_crop crop;
- v4l2_rect &c = crop.c;
+ v4l2_selection sel;
+ v4l2_rect &r = sel.r;
+ v4l2_rect b = { 0, 0, m_width, m_height };
- cropcap.type = crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (cv4l_ioctl(VIDIOC_CROPCAP, &cropcap) ||
- cv4l_ioctl(VIDIOC_G_CROP, &crop))
+ sel.type = g_selection_type();
+ if (sel.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ sel.target = V4L2_SEL_TGT_CROP_BOUNDS;
+ if (g_selection(sel))
+ return;
+ b = sel.r;
+ }
+ sel.target = V4L2_SEL_TGT_CROP;
+ if (g_selection(sel))
return;
m_cropWidth->blockSignals(true);
m_cropTop->blockSignals(true);
m_cropWidth->setRange(8, b.width);
- m_cropWidth->setSliderPosition(c.width);
- if (b.width != c.width) {
- m_cropLeft->setRange(b.left, b.left + b.width - c.width);
- m_cropLeft->setSliderPosition(c.left);
+ m_cropWidth->setSliderPosition(r.width);
+ if (b.width != r.width) {
+ m_cropLeft->setRange(b.left, b.left + b.width - r.width);
+ m_cropLeft->setSliderPosition(r.left);
}
m_cropHeight->setRange(8, b.height);
- m_cropHeight->setSliderPosition(c.height);
- if (b.height != c.height) {
- m_cropTop->setRange(b.top, b.top + b.height - c.height);
- m_cropTop->setSliderPosition(c.top);
+ m_cropHeight->setSliderPosition(r.height);
+ if (b.height != r.height) {
+ m_cropTop->setRange(b.top, b.top + b.height - r.height);
+ m_cropTop->setSliderPosition(r.top);
}
m_cropWidth->blockSignals(false);
v4l2_selection sel;
v4l2_rect &r = sel.r;
+ v4l2_rect b = { 0, 0, m_width, m_height };
- sel.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ sel.type = g_selection_type();
+ if (sel.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ sel.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
+ if (g_selection(sel))
+ return;
+ b = sel.r;
+ }
sel.target = V4L2_SEL_TGT_COMPOSE;
- if (cv4l_ioctl(VIDIOC_G_SELECTION, &sel))
+ if (g_selection(sel))
return;
m_composeWidth->blockSignals(true);
m_composeHeight->blockSignals(true);
m_composeTop->blockSignals(true);
- m_composeWidth->setRange(8, m_width);
+ m_composeWidth->setRange(8, b.width);
m_composeWidth->setSliderPosition(r.width);
- if (m_width != r.width) {
- m_composeLeft->setRange(0, m_width - r.width);
+ if (b.width != r.width) {
+ m_composeLeft->setRange(b.left, b.left + b.width - r.width);
m_composeLeft->setSliderPosition(r.left);
}
- m_composeHeight->setRange(8, m_height);
+ m_composeHeight->setRange(8, b.height);
m_composeHeight->setSliderPosition(r.height);
- if (m_height != r.height) {
- m_composeTop->setRange(0, m_height - r.height);
+ if (b.height != r.height) {
+ m_composeTop->setRange(b.top, b.top + b.height - r.height);
m_composeTop->setSliderPosition(r.top);
}
int g_fmt(v4l2_format &fmt, unsigned type = 0) { return m_fd->g_fmt(fmt); }
int try_fmt(v4l2_format &fmt) { return m_fd->try_fmt(fmt); }
int s_fmt(v4l2_format &fmt) { return m_fd->s_fmt(fmt); }
+ int g_selection(v4l2_selection &sel) { return m_fd->g_selection(sel); }
+ int s_selection(v4l2_selection &sel) { return m_fd->s_selection(sel); }
int g_tuner(v4l2_tuner &tuner, unsigned index = 0) { return m_fd->g_tuner(tuner, index); }
int s_tuner(v4l2_tuner &tuner) { return m_fd->g_tuner(tuner); }
int g_modulator(v4l2_modulator &modulator) { return m_fd->g_modulator(modulator); }
}
bool has_crop() { return m_fd->has_crop(); }
bool has_compose() { return m_fd->has_compose(); }
- bool input_has_crop() { return m_fd->input_has_crop(); }
- bool input_has_compose() { return m_fd->input_has_compose(); }
+ bool cur_io_has_crop() { return m_fd->cur_io_has_crop(); }
+ bool cur_io_has_compose() { return m_fd->cur_io_has_compose(); }
bool ioctl_exists(int ret)
{
return ret == 0 || errno != ENOTTY;
cv4l_buffer buf;
m_queue.buffer_init(buf, i);
+ buf.s_field(m_tpgField);
+ tpg_s_field(&m_tpg, m_tpgField);
+ if (m_tpgField == V4L2_FIELD_TOP)
+ m_tpgField = V4L2_FIELD_BOTTOM;
+ else if (m_tpgField == V4L2_FIELD_BOTTOM)
+ m_tpgField = V4L2_FIELD_TOP;
for (unsigned p = 0; p < m_queue.g_num_planes(); p++)
tpg_fillbuffer(&m_tpg, m_tpgStd, p, (u8 *)m_queue.g_dataptr(i, p));
qbuf(buf);
return;
}
m_queue.buffer_init(buf, buf.g_index());
+ buf.s_field(m_tpgField);
+ tpg_s_field(&m_tpg, m_tpgField);
+ if (m_tpgField == V4L2_FIELD_TOP)
+ m_tpgField = V4L2_FIELD_BOTTOM;
+ else if (m_tpgField == V4L2_FIELD_BOTTOM)
+ m_tpgField = V4L2_FIELD_TOP;
for (unsigned p = 0; p < m_queue.g_num_planes(); p++)
tpg_fillbuffer(&m_tpg, m_tpgStd, p, (u8 *)m_queue.g_dataptr(buf.g_index(), p));
tpg_update_mv_count(&m_tpg, V4L2_FIELD_HAS_T_OR_B(m_tpgField));
g_std(m_tpgStd);
else
m_tpgStd = 0;
- m_tpgField = fmt.g_field();
+ m_tpgField = fmt.g_first_field(m_tpgStd);
m_tpgSizeImage = fmt.g_sizeimage(0);
tpg_alloc(&m_tpg, fmt.g_width());
m_useTpg = tpg_s_fourcc(&m_tpg, fmt.g_pixelformat());
return v4l_s_fmt(this, &fmt);
}
+ int g_selection(v4l2_selection &sel)
+ {
+ return v4l_g_selection(this, &sel);
+ }
+
+ int s_selection(v4l2_selection &sel)
+ {
+ return v4l_s_selection(this, &sel);
+ }
+
int g_tuner(v4l2_tuner &tuner, unsigned index = 0)
{
memset(&tuner, 0, sizeof(tuner));
bool has_crop()
{
- v4l2_crop crop;
- v4l2_cropcap cropcap;
+ v4l2_selection sel;
- crop.type = g_selection_type();
- cropcap.type = crop.type;
- return ioctl_exists(cv4l_ioctl(VIDIOC_G_CROP, &crop)) &&
- ioctl_exists(cv4l_ioctl(VIDIOC_S_CROP, &crop)) &&
- ioctl_exists(cv4l_ioctl(VIDIOC_CROPCAP, &cropcap));
+ memset(&sel, 0, sizeof(sel));
+ sel.type = g_selection_type();
+ sel.target = V4L2_SEL_TGT_CROP;
+ return ioctl_exists(g_selection(sel));
}
bool has_compose()
memset(&sel, 0, sizeof(sel));
sel.type = g_selection_type();
sel.target = V4L2_SEL_TGT_COMPOSE;
- return ioctl_exists(cv4l_ioctl(VIDIOC_G_SELECTION, &sel)) &&
- ioctl_exists(cv4l_ioctl(VIDIOC_S_SELECTION, &sel));
+ return ioctl_exists(g_selection(sel));
}
- bool input_has_crop()
+ bool cur_io_has_crop()
{
- v4l2_crop crop;
- v4l2_cropcap cropcap;
+ v4l2_selection sel;
- crop.type = g_selection_type();
- cropcap.type = crop.type;
- return cv4l_ioctl(VIDIOC_G_CROP, &crop) == 0 &&
- cv4l_ioctl(VIDIOC_S_CROP, &crop) == 0 &&
- cv4l_ioctl(VIDIOC_CROPCAP, &cropcap) == 0 &&
- cropcap.bounds.width && cropcap.bounds.height;
+ memset(&sel, 0, sizeof(sel));
+ sel.type = g_selection_type();
+ sel.target = V4L2_SEL_TGT_CROP;
+ return g_selection(sel) == 0;
}
- bool input_has_compose()
+ bool cur_io_has_compose()
{
v4l2_selection sel;
memset(&sel, 0, sizeof(sel));
sel.type = g_selection_type();
sel.target = V4L2_SEL_TGT_COMPOSE;
- return cv4l_ioctl(VIDIOC_G_SELECTION, &sel) == 0 &&
- cv4l_ioctl(VIDIOC_S_SELECTION, &sel) == 0;
+ return g_selection(sel) == 0;
}
int subscribe_event(v4l2_event_subscription &sub)
bool have_query_ext_ctrl;
bool have_ext_ctrls;
bool have_next_ctrl;
+ bool have_selection;
int (*open)(struct v4l_fd *f, const char *file, int oflag, ...);
int (*close)(struct v4l_fd *f);
struct v4l2_query_ext_ctrl qec = { V4L2_CTRL_FLAG_NEXT_CTRL };
struct v4l2_ext_controls ec = { 0, 0 };
struct v4l2_queryctrl qc = { V4L2_CTRL_FLAG_NEXT_CTRL };
+ struct v4l2_selection sel = { 0 };
f->fd = f->open(f, devname, O_RDWR | (non_blocking ? O_NONBLOCK : 0));
v4l_close(f);
return -1;
}
+ f->caps = v4l_capability_g_caps(&f->cap);
+ f->type = v4l_determine_type(f);
+
f->have_query_ext_ctrl = v4l_ioctl(f, VIDIOC_QUERY_EXT_CTRL, &qec) == 0;
f->have_ext_ctrls = v4l_ioctl(f, VIDIOC_TRY_EXT_CTRLS, &ec) == 0;
f->have_next_ctrl = v4l_ioctl(f, VIDIOC_QUERYCTRL, &qc) == 0;
+ sel.type = v4l_g_selection_type(f);
+ sel.target = sel.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
+ V4L2_SEL_TGT_CROP : V4L2_SEL_TGT_COMPOSE;
+ f->have_selection = v4l_ioctl(f, VIDIOC_G_SELECTION, &sel) == 0;
- f->caps = v4l_capability_g_caps(&f->cap);
- f->type = v4l_determine_type(f);
return f->fd;
}
return 0;
}
+static inline int v4l_g_selection(v4l_fd *f, struct v4l2_selection *sel)
+{
+ struct v4l2_cropcap cc;
+ struct v4l2_crop crop;
+ int ret;
+
+ if (f->have_selection)
+ return v4l_ioctl(f, VIDIOC_G_SELECTION, sel);
+ crop.type = sel->type;
+ cc.type = sel->type;
+ ret = v4l_ioctl(f, VIDIOC_CROPCAP, &cc);
+ if (ret)
+ return ret;
+ ret = v4l_ioctl(f, VIDIOC_G_CROP, &crop);
+ if (ret)
+ return ret;
+ if (sel->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ switch (sel->target) {
+ case V4L2_SEL_TGT_CROP:
+ sel->r = crop.c;
+ return 0;
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ sel->r = cc.defrect;
+ return 0;
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ sel->r = cc.bounds;
+ return 0;
+ default:
+ return EINVAL;
+ }
+ }
+ switch (sel->target) {
+ case V4L2_SEL_TGT_COMPOSE:
+ sel->r = crop.c;
+ return 0;
+ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+ sel->r = cc.defrect;
+ return 0;
+ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+ sel->r = cc.bounds;
+ return 0;
+ default:
+ return EINVAL;
+ }
+}
+
+static inline int v4l_s_selection(v4l_fd *f, struct v4l2_selection *sel)
+{
+ struct v4l2_crop crop;
+ int ret;
+
+ if (f->have_selection)
+ return v4l_ioctl(f, VIDIOC_S_SELECTION, sel);
+ crop.type = sel->type;
+ ret = v4l_ioctl(f, VIDIOC_G_CROP, &crop);
+ if (ret)
+ return ret;
+ if (sel->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ sel->target == V4L2_SEL_TGT_CROP) {
+ crop.c = sel->r;
+ return v4l_ioctl(f, VIDIOC_S_CROP, &crop);
+ }
+ if (sel->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ sel->target == V4L2_SEL_TGT_COMPOSE) {
+ crop.c = sel->r;
+ return v4l_ioctl(f, VIDIOC_S_CROP, &crop);
+ }
+ return EINVAL;
+}
+
#ifdef __cplusplus
}
#endif /* __cplusplus */