Subscribe to source change event. The capture setup sequence is executed only due to a change event. Signed-off-by: Dafna Hirschfeld <dafna3@xxxxxxxxx> --- utils/v4l2-ctl/v4l2-ctl-streaming.cpp | 90 ++++++++++++++++++++++----- 1 file changed, 76 insertions(+), 14 deletions(-) diff --git a/utils/v4l2-ctl/v4l2-ctl-streaming.cpp b/utils/v4l2-ctl/v4l2-ctl-streaming.cpp index cd20dec7..61dd84db 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') @@ -755,8 +756,11 @@ 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()); - unsigned coded_height = fmt.g_height(); + const struct v4l2_fwht_pixfmt_info *vic_fmt; + const static struct v4l2_fwht_pixfmt_info *old_info = + v4l2_fwht_find_pixfmt(fmt.g_pixelformat()); + static cv4l_fmt old_fmt = fmt; + unsigned coded_height; unsigned real_width; unsigned real_height; unsigned char *plane_p = buf; @@ -770,6 +774,21 @@ static void read_write_padded_frame(cv4l_fmt &fmt, unsigned char *buf, real_height = composed_height; } + /* + * if the source change event was dequeued but the stream was not yet + * restarted then the current buffers still fit the old resolution so + * we need to save it + */ + if (in_source_change_event) { + vic_fmt = old_info; + fmt = old_fmt; + } else { + vic_fmt = v4l2_fwht_find_pixfmt(fmt.g_pixelformat()); + old_info = vic_fmt; + old_fmt = fmt; + } + + coded_height = fmt.g_height(); sz = 0; len = real_width * real_height * vic_fmt->sizeimage_mult / vic_fmt->sizeimage_div; @@ -1208,8 +1227,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(); @@ -1890,6 +1919,7 @@ 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; if (!fd.has_vid_m2m()) { fprintf(stderr, "unsupported m2m stream type\n"); @@ -1920,6 +1950,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; @@ -1941,6 +1976,10 @@ static void streaming_set_m2m(cv4l_fd &fd) return; } } + enum codec_type codec_type; + + if (get_codec_type(fd, codec_type)) + goto done; if (out.reqbufs(&fd, reqbufs_count_out)) goto done; @@ -1951,8 +1990,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 != DECODER) + 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()); @@ -1999,12 +2039,25 @@ 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); - break; + 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"); + + /* + * if capture is already streaming, + * wait to the a capture buffer with + * LAST_BUFFER flag + */ + if (cap_streaming) { + in_source_change_event = true; + continue; + } + if (capture_setup(fd, in)) + goto done; + } } } @@ -2018,8 +2071,17 @@ static void streaming_set_m2m(cv4l_fd &fd) break; } } - if (last_buffer) - break; + if (last_buffer) { + if (in_source_change_event) { + in_source_change_event = false; + last_buffer = false; + if (capture_setup(fd, in)) + goto done; + cap_streaming = true; + } else { + break; + } + } } if (wr_fds && FD_ISSET(fd.g_fd(), wr_fds)) { -- 2.17.1