On 01/20/2019 12:15 PM, Dafna Hirschfeld wrote:
> Subscribe to source change event.
> The capture setup sequence is executed only due to a
> change event.
>
> Signed-off-by: Dafna Hirschfeld <[email protected]>
> ---
> 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;
I would change this to:
in_source_change_event = true;
if (!cap_streaming)
last_buffer = true;
This simplifies the code since you don't have to call capture_setup
here anymore.
> + }
> }
> }
>
> @@ -2018,8 +2071,17 @@ static void streaming_set_m2m(cv4l_fd &fd)
> break;
> }
> }
> - if (last_buffer)
> - break;
Keep this...
> + 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;
> + }
> + }
...and move this to just before the end of the 'while (rd_fds || wr_fds ||
ex_fds)' loop.
That avoids the need for patch 3/6, unless I missed something.
> }
>
> if (wr_fds && FD_ISSET(fd.g_fd(), wr_fds)) {
>
Regards,
Hans