aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDafna Hirschfeld <dafna3@gmail.com>2019-01-21 18:56:50 (GMT)
committerHans Verkuil <hverkuil-cisco@xs4all.nl>2019-01-28 09:03:42 (GMT)
commit93d0305be64995d918a203c3b6c96fbca3fae4b0 (patch)
treef503dee7c1ef0eb03dc9088d986f6cccb85bfa0d
parent442c026cb9ac75ff6fb10c2c165a5ee8f7664b44 (diff)
v4l2-ctl: Add support for source change event for m2m decoder
Subscribe to source change event. The capture setup sequence is executed only due to a change event. Signed-off-by: Dafna Hirschfeld <dafna3@gmail.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-rw-r--r--utils/v4l2-ctl/v4l2-ctl-streaming.cpp112
1 files changed, 85 insertions, 27 deletions
diff --git a/utils/v4l2-ctl/v4l2-ctl-streaming.cpp b/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
index d74a6c0..8d034b8 100644
--- a/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
@@ -78,6 +78,7 @@ static unsigned int composed_width;
static unsigned int composed_height;
static bool support_cap_compose;
static bool support_out_crop;
+static bool in_source_change_event;
#define TS_WINDOW 241
#define FILE_HDR_ID v4l2_fourcc('V', 'h', 'd', 'r')
@@ -752,7 +753,8 @@ static void read_write_padded_frame(cv4l_fmt &fmt, unsigned char *buf,
FILE *fpointer, unsigned &sz,
unsigned &len, bool is_read)
{
- const struct v4l2_fwht_pixfmt_info *vic_fmt = v4l2_fwht_find_pixfmt(fmt.g_pixelformat());
+ const struct v4l2_fwht_pixfmt_info *vic_fmt =
+ v4l2_fwht_find_pixfmt(fmt.g_pixelformat());
unsigned coded_height = fmt.g_height();
unsigned real_width;
unsigned real_height;
@@ -801,7 +803,8 @@ static void read_write_padded_frame(cv4l_fmt &fmt, unsigned char *buf,
}
}
-static bool fill_buffer_from_file(cv4l_fd &fd, cv4l_queue &q, cv4l_buffer &b, FILE *fin)
+static bool fill_buffer_from_file(cv4l_fd &fd, cv4l_queue &q, cv4l_buffer &b,
+ cv4l_fmt &fmt, FILE *fin)
{
static bool first = true;
static bool is_fwht = false;
@@ -1059,7 +1062,7 @@ static int do_setup_out_buffers(cv4l_fd &fd, cv4l_queue &q, FILE *fin, bool qbuf
tpg_fillbuffer(&tpg, stream_out_std, j, (u8 *)q.g_dataptr(i, j));
}
}
- if (fin && !fill_buffer_from_file(fd, q, buf, fin))
+ if (fin && !fill_buffer_from_file(fd, q, buf, fmt, fin))
return -2;
if (qbuf) {
@@ -1077,7 +1080,8 @@ static int do_setup_out_buffers(cv4l_fd &fd, cv4l_queue &q, FILE *fin, bool qbuf
return 0;
}
-static void write_buffer_to_file(cv4l_fd &fd, cv4l_queue &q, cv4l_buffer &buf, FILE *fout)
+static void write_buffer_to_file(cv4l_fd &fd, cv4l_queue &q, cv4l_buffer &buf,
+ cv4l_fmt &fmt, FILE *fout)
{
#ifndef NO_STREAM_TO
unsigned comp_size[VIDEO_MAX_PLANES];
@@ -1118,9 +1122,7 @@ static void write_buffer_to_file(cv4l_fd &fd, cv4l_queue &q, cv4l_buffer &buf, F
__u32 used = buf.g_bytesused();
unsigned offset = buf.g_data_offset();
unsigned sz;
- cv4l_fmt fmt;
- fd.g_fmt(fmt, q.g_type());
if (offset > used) {
// Should never happen
fprintf(stderr, "offset %d > used %d!\n",
@@ -1153,7 +1155,7 @@ static void write_buffer_to_file(cv4l_fd &fd, cv4l_queue &q, cv4l_buffer &buf, F
}
static int do_handle_cap(cv4l_fd &fd, cv4l_queue &q, FILE *fout, int *index,
- unsigned &count, fps_timestamps &fps_ts)
+ unsigned &count, fps_timestamps &fps_ts, cv4l_fmt &fmt)
{
char ch = '<';
int ret;
@@ -1192,7 +1194,7 @@ static int do_handle_cap(cv4l_fd &fd, cv4l_queue &q, FILE *fout, int *index,
if (fout && (!stream_skip || ignore_count_skip) &&
buf.g_bytesused(0) && !(buf.g_flags() & V4L2_BUF_FLAG_ERROR))
- write_buffer_to_file(fd, q, buf, fout);
+ write_buffer_to_file(fd, q, buf, fmt, fout);
if (buf.g_flags() & V4L2_BUF_FLAG_KEYFRAME)
ch = 'K';
@@ -1205,8 +1207,18 @@ static int do_handle_cap(cv4l_fd &fd, cv4l_queue &q, FILE *fout, int *index,
host_fd_to >= 0 ? 100 - comp_perc / comp_perc_count : -1);
comp_perc_count = comp_perc = 0;
}
- if (!last_buffer && index == NULL && fd.qbuf(buf))
- return -1;
+ if (!last_buffer && index == NULL) {
+ /*
+ * EINVAL in qbuf can happen if this is the last buffer before
+ * a dynamic resolution change sequence. In this case the buffer
+ * has the size that fits the old resolution and might not
+ * fit to the new one.
+ */
+ if (fd.qbuf(buf) && errno != EINVAL) {
+ fprintf(stderr, "%s: qbuf error\n", __func__);
+ return -1;
+ }
+ }
if (index)
*index = buf.g_index();
@@ -1246,7 +1258,7 @@ static int do_handle_cap(cv4l_fd &fd, cv4l_queue &q, FILE *fout, int *index,
}
static int do_handle_out(cv4l_fd &fd, cv4l_queue &q, FILE *fin, cv4l_buffer *cap,
- unsigned &count, fps_timestamps &fps_ts)
+ unsigned &count, fps_timestamps &fps_ts, cv4l_fmt fmt)
{
cv4l_buffer buf(q);
int ret = 0;
@@ -1291,7 +1303,7 @@ static int do_handle_out(cv4l_fd &fd, cv4l_queue &q, FILE *fin, cv4l_buffer *cap
output_field = V4L2_FIELD_TOP;
}
- if (fin && !fill_buffer_from_file(fd, q, buf, fin))
+ if (fin && !fill_buffer_from_file(fd, q, buf, fmt, fin))
return -2;
if (!fin && stream_out_refresh) {
@@ -1365,6 +1377,9 @@ static void streaming_set_cap(cv4l_fd &fd)
bool eos;
bool source_change;
FILE *fout = NULL;
+ cv4l_fmt fmt;
+
+ fd.g_fmt(fmt);
if (!(capabilities & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE |
V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE |
@@ -1573,7 +1588,7 @@ recover:
if (FD_ISSET(fd.g_fd(), &read_fds)) {
r = do_handle_cap(fd, q, fout, NULL,
- count, fps_ts);
+ count, fps_ts, fmt);
if (r == -1)
break;
}
@@ -1605,6 +1620,9 @@ static void streaming_set_out(cv4l_fd &fd)
fps_timestamps fps_ts;
unsigned count = 0;
FILE *fin = NULL;
+ cv4l_fmt fmt;
+
+ fd.g_fmt(fmt);
if (!(capabilities & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE |
V4L2_CAP_VBI_OUTPUT | V4L2_CAP_SLICED_VBI_OUTPUT |
@@ -1806,7 +1824,7 @@ static void streaming_set_out(cv4l_fd &fd)
}
}
r = do_handle_out(fd, q, fin, NULL,
- count, fps_ts);
+ count, fps_ts, fmt);
if (r == -1)
break;
@@ -1875,6 +1893,11 @@ static void streaming_set_m2m(cv4l_fd &fd)
fd_set *rd_fds = &fds[0]; /* for capture */
fd_set *ex_fds = &fds[1]; /* for capture */
fd_set *wr_fds = &fds[2]; /* for output */
+ bool cap_streaming = false;
+ cv4l_fmt fmt[2];
+
+ fd.g_fmt(fmt[OUT], out.g_type());
+ fd.g_fmt(fmt[CAP], in.g_type());
if (!fd.has_vid_m2m()) {
fprintf(stderr, "unsupported m2m stream type\n");
@@ -1897,6 +1920,10 @@ static void streaming_set_m2m(cv4l_fd &fd)
bool have_eos = !fd.subscribe_event(sub);
bool is_encoder = false;
+ enum codec_type codec_type = get_codec_type(fd);
+
+ if (codec_type == NOT_CODEC)
+ goto done;
if (have_eos) {
cv4l_fmt fmt(in.g_type());
@@ -1905,6 +1932,11 @@ static void streaming_set_m2m(cv4l_fd &fd)
is_encoder = !fmt.g_bytesperline();
}
+ memset(&sub, 0, sizeof(sub));
+ sub.type = V4L2_EVENT_SOURCE_CHANGE;
+ if (fd.subscribe_event(sub))
+ goto done;
+
if (file_to) {
if (!strcmp(file_to, "-"))
file[CAP] = stdout;
@@ -1936,8 +1968,9 @@ static void streaming_set_m2m(cv4l_fd &fd)
if (fd.streamon(out.g_type()))
goto done;
- if (capture_setup(fd, in))
- goto done;
+ if (codec_type == ENCODER)
+ if (capture_setup(fd, in))
+ goto done;
fps_ts[CAP].determine_field(fd.g_fd(), in.g_type());
fps_ts[OUT].determine_field(fd.g_fd(), out.g_type());
@@ -1982,7 +2015,7 @@ static void streaming_set_m2m(cv4l_fd &fd)
if (rd_fds && FD_ISSET(fd.g_fd(), rd_fds)) {
r = do_handle_cap(fd, in, file[CAP], NULL,
- count[CAP], fps_ts[CAP]);
+ count[CAP], fps_ts[CAP], fmt[CAP]);
if (r < 0) {
rd_fds = NULL;
if (!have_eos) {
@@ -1990,13 +2023,11 @@ static void streaming_set_m2m(cv4l_fd &fd)
break;
}
}
- if (last_buffer)
- break;
}
if (wr_fds && FD_ISSET(fd.g_fd(), wr_fds)) {
r = do_handle_out(fd, out, file[OUT], NULL,
- count[OUT], fps_ts[OUT]);
+ count[OUT], fps_ts[OUT], fmt[OUT]);
if (r < 0) {
wr_fds = NULL;
@@ -2022,11 +2053,35 @@ static void streaming_set_m2m(cv4l_fd &fd)
struct v4l2_event ev;
while (!fd.dqevent(ev)) {
- if (ev.type != V4L2_EVENT_EOS)
- continue;
- wr_fds = NULL;
- fprintf(stderr, "EOS");
- fflush(stderr);
+ if (ev.type == V4L2_EVENT_EOS) {
+ wr_fds = NULL;
+ fprintf(stderr, "EOS");
+ fflush(stderr);
+ } else if (ev.type == V4L2_EVENT_SOURCE_CHANGE) {
+ fprintf(stderr, "SOURCE CHANGE\n");
+ in_source_change_event = true;
+
+ /*
+ * if capture is not streaming, the
+ * driver will not send a last buffer so
+ * we set it here
+ */
+ if (!cap_streaming)
+ last_buffer = true;
+ }
+ }
+ }
+
+ if (last_buffer) {
+ if (in_source_change_event) {
+ in_source_change_event = false;
+ last_buffer = false;
+ if (capture_setup(fd, in))
+ goto done;
+ fd.g_fmt(fmt[OUT], out.g_type());
+ fd.g_fmt(fmt[CAP], in.g_type());
+ cap_streaming = true;
+ } else {
break;
}
}
@@ -2063,7 +2118,10 @@ static void streaming_set_cap2out(cv4l_fd &fd, cv4l_fd &out_fd)
FILE *file[2] = {NULL, NULL};
fd_set fds;
unsigned cnt = 0;
+ cv4l_fmt fmt[2];
+ fd.g_fmt(fmt[OUT], out.g_type());
+ fd.g_fmt(fmt[CAP], in.g_type());
if (!(capabilities & (V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_VIDEO_CAPTURE_MPLANE |
V4L2_CAP_VIDEO_M2M |
@@ -2179,7 +2237,7 @@ static void streaming_set_cap2out(cv4l_fd &fd, cv4l_fd &out_fd)
int index = -1;
r = do_handle_cap(fd, in, file[CAP], &index,
- count[CAP], fps_ts[CAP]);
+ count[CAP], fps_ts[CAP], fmt[CAP]);
if (r)
fprintf(stderr, "handle cap %d\n", r);
if (!r) {
@@ -2188,7 +2246,7 @@ static void streaming_set_cap2out(cv4l_fd &fd, cv4l_fd &out_fd)
if (fd.querybuf(buf))
break;
r = do_handle_out(out_fd, out, file[OUT], &buf,
- count[OUT], fps_ts[OUT]);
+ count[OUT], fps_ts[OUT], fmt[OUT]);
}
if (r)
fprintf(stderr, "handle out %d\n", r);

Privacy Policy