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 <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;

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

Reply via email to