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 | 112 +++++++++++++++++++-------
 1 file changed, 85 insertions(+), 27 deletions(-)

diff --git a/utils/v4l2-ctl/v4l2-ctl-streaming.cpp 
b/utils/v4l2-ctl/v4l2-ctl-streaming.cpp
index d74a6c0b..8d034b85 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);
-- 
2.17.1

Reply via email to