summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kms++util/inc/kms++util/videodevice.h2
-rw-r--r--kms++util/src/videodevice.cpp67
-rw-r--r--py/pykms/pyvid.cpp9
3 files changed, 78 insertions, 0 deletions
diff --git a/kms++util/inc/kms++util/videodevice.h b/kms++util/inc/kms++util/videodevice.h
index 68e2b01..e089bcd 100644
--- a/kms++util/inc/kms++util/videodevice.h
+++ b/kms++util/inc/kms++util/videodevice.h
@@ -71,6 +71,8 @@ public:
std::vector<kms::PixelFormat> get_formats();
void set_format(kms::PixelFormat fmt, uint32_t width, uint32_t height);
+ void get_selection(uint32_t& left, uint32_t& top, uint32_t& width, uint32_t& height);
+ void set_selection(uint32_t& left, uint32_t& top, uint32_t& width, uint32_t& height);
void set_queue_size(uint32_t queue_size);
void queue(kms::DumbFramebuffer* fb);
kms::DumbFramebuffer* dequeue();
diff --git a/kms++util/src/videodevice.cpp b/kms++util/src/videodevice.cpp
index efe1678..cc11357 100644
--- a/kms++util/src/videodevice.cpp
+++ b/kms++util/src/videodevice.cpp
@@ -96,6 +96,63 @@ static void v4l2_set_format(int fd, PixelFormat fmt, uint32_t width, uint32_t he
}
}
+static void v4l2_get_selection(int fd, uint32_t& left, uint32_t& top, uint32_t& width, uint32_t& height, uint32_t buf_type)
+{
+ int r;
+ struct v4l2_selection selection;
+
+ if (buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+ buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ selection.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ selection.target = V4L2_SEL_TGT_CROP;
+ } else if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ selection.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ selection.target = V4L2_SEL_TGT_COMPOSE;
+ } else {
+ FAIL("buf_type (%d) is not valid\n", buf_type);
+ }
+
+ r = ioctl(fd, VIDIOC_G_SELECTION, &selection);
+ ASSERT(r == 0);
+
+ left = selection.r.left;
+ top = selection.r.top;
+ width = selection.r.width;
+ height = selection.r.height;
+}
+
+static void v4l2_set_selection(int fd, uint32_t& left, uint32_t& top, uint32_t& width, uint32_t& height, uint32_t buf_type)
+{
+ int r;
+ struct v4l2_selection selection;
+
+ if (buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+ buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ selection.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ selection.target = V4L2_SEL_TGT_CROP;
+ } else if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ selection.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ selection.target = V4L2_SEL_TGT_COMPOSE;
+ } else {
+ FAIL("buf_type (%d) is not valid\n", buf_type);
+ }
+
+ selection.r.left = left;
+ selection.r.top = top;
+ selection.r.width = width;
+ selection.r.height = height;
+
+ r = ioctl(fd, VIDIOC_S_SELECTION, &selection);
+ ASSERT(r == 0);
+
+ left = selection.r.left;
+ top = selection.r.top;
+ width = selection.r.width;
+ height = selection.r.height;
+}
+
static void v4l2_request_bufs(int fd, uint32_t queue_size, uint32_t buf_type)
{
v4l2_requestbuffers v4lreqbuf { };
@@ -414,6 +471,16 @@ void VideoStreamer::set_format(PixelFormat fmt, uint32_t width, uint32_t height)
v4l2_set_format(m_fd, fmt, width, height, get_buf_type(m_type));
}
+void VideoStreamer::get_selection(uint32_t& left, uint32_t& top, uint32_t& width, uint32_t& height)
+{
+ v4l2_get_selection(m_fd, left, top, width, height, get_buf_type(m_type));
+}
+
+void VideoStreamer::set_selection(uint32_t& left, uint32_t& top, uint32_t& width, uint32_t& height)
+{
+ v4l2_set_selection(m_fd, left, top, width, height, get_buf_type(m_type));
+}
+
void VideoStreamer::set_queue_size(uint32_t queue_size)
{
v4l2_request_bufs(m_fd, queue_size, get_buf_type(m_type));
diff --git a/py/pykms/pyvid.cpp b/py/pykms/pyvid.cpp
index 92006c4..8b0450a 100644
--- a/py/pykms/pyvid.cpp
+++ b/py/pykms/pyvid.cpp
@@ -30,6 +30,15 @@ void init_pyvid(py::module &m)
.def("set_port", &VideoStreamer::set_port)
.def_property_readonly("formats", &VideoStreamer::get_formats)
.def("set_format", &VideoStreamer::set_format)
+ .def("get_selection", [](VideoStreamer *self) {
+ uint32_t left, top, width, height;
+ self->get_selection(left, top, width, height);
+ return make_tuple(left, top, width, height);
+ } )
+ .def("set_selection", [](VideoStreamer *self, uint32_t left, uint32_t top, uint32_t width, uint32_t height) {
+ self->set_selection(left, top, width, height);
+ return make_tuple(left, top, width, height);
+ } )
.def("set_queue_size", &VideoStreamer::set_queue_size)
.def("queue", &VideoStreamer::queue)
.def("dequeue", &VideoStreamer::dequeue)