Subscribe to source change event.
The capture setup sequence is executed only due to a
change event.

Signed-off-by: Dafna Hirschfeld <daf...@gmail.com>
---
 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

Reply via email to