Re: [PATCH v4l-utils] v4l2-ctl: Add support for CROP selection in m2m streaming

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Dec 19, 2018 at 12:03 PM Hans Verkuil <hverkuil@xxxxxxxxx> wrote:
>
> On 12/19/18 9:34 AM, Dafna Hirschfeld wrote:
> >>> +bool is_m2m_enc = false;
> >>
> >> This should be static.
> >>
> >> I'm assuming that in a future patch we'll get a is_m2m_dec as well?
> >
> > I forgot that there can be more options other than m2m_enc/_dec.
> > So actually adding is_m2m_dec is needed. Or I can define an enum with
> > 3 possible values
> > IS_M2M_ENC, IS_M2M_DEC, NOT_M2M_DEV
>
> I think using bools will make the code easier.
>
> >
> >>
> >>> +
> >>>  #define TS_WINDOW 241
> >>>  #define FILE_HDR_ID                  v4l2_fourcc('V', 'h', 'd', 'r')
> >>>
> >>> @@ -108,6 +114,84 @@ public:
> >>>       unsigned dropped();
> >>>  };
> >>>
> >>> +static int get_codec_type(int fd, bool &is_enc) {
> >>
> >> { on the next line.
> >>
> >>> +     struct v4l2_capability vcap;
> >>> +
> >>> +     memset(&vcap,0,sizeof(vcap));
> >>
> >> Space after ,
> >>
> >> Please use the kernel coding style for these v4l utilities.
> >>
> > I ran the checkpatch script on this file and it didn't catch theses things.
> > Do you use checkpatch for v4l-utils ?
>
> No. As far as I can tell checkpatch skips cpp files so it can't be used for C++ files.
>
> >
> >>> +
> >>> +     int ret = ioctl(fd, VIDIOC_QUERYCAP, &vcap);
> >>
> >> Please use the cv4l_fd class. It comes with lots of helpers for all these ioctls
> >> and it already used in v4l2-ctl-streaming.cpp.
> >>
> >> In this function you can just do:
> >>
> >>         if (!fd.has_vid_m2m())
> >>                 return -1;
> >>
> >>> +     if(ret) {
> >>> +             fprintf(stderr, "get_codec_type: VIDIOC_QUERYCAP failed: %d\n", ret);
> >>> +             return ret;
> >>> +     }
> >>> +     unsigned int caps = vcap.capabilities;
> >>> +     if (caps & V4L2_CAP_DEVICE_CAPS)
> >>> +             caps = vcap.device_caps;
> >>> +     if(!(caps & V4L2_CAP_VIDEO_M2M) && !(caps & V4L2_CAP_VIDEO_M2M_MPLANE)) {
> >>> +             is_enc = false;
> >>> +             fprintf(stderr,"get_codec_type: not an M2M device\n");
> >>> +             return -1;
> >>> +     }
> >>> +
> >>> +     struct v4l2_fmtdesc fmt;
> >>> +     memset(&fmt,0,sizeof(fmt));
> >>> +     fmt.index = 0;
> >>> +     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> >>> +
> >>> +     while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmt)) == 0) {
> >>> +             if((fmt.flags & V4L2_FMT_FLAG_COMPRESSED) == 0)
> >>> +                     break;
> >>> +             fmt.index++;
> >>> +     }
> >>
> >> These tests aren't good enough. You need to enumerate over all formats.
> >> Easiest is to keep a tally of the total number of formats and how many
> >> are compressed.
> >>
> >> An encoder is a device where all output formats are uncompressed and
> >> all capture formats are compressed. It's the reverse for a decoder.
> >>
> >> If you get a mix on either side, or both sides are raw or both sides
> >> are compressed, then it isn't a codec.
> >>
> >>> +     if (ret) {
> >>> +             is_enc = true;
> >>> +             return 0;
> >>> +     }
> >>> +     memset(&fmt,0,sizeof(fmt));
> >>> +     fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
> >>> +     while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmt)) == 0) {
> >>> +             if((fmt.flags & V4L2_FMT_FLAG_COMPRESSED) == 0)
> >>> +                     break;
> >>> +             fmt.index++;
> >>> +     }
> >>> +     if (ret) {
> >>> +             is_enc = false;
> >>> +             return 0;
> >>> +     }
> >>> +     fprintf(stderr, "get_codec_type: could no determine codec type\n");
> >>> +     return -1;
> >>> +}
> >>> +
> >>> +static void get_frame_dims(unsigned int &frame_width, unsigned int &frame_height) {
> >>> +
> >>> +     if(is_m2m_enc)
> >>> +             vidout_get_orig_from_set(frame_width, frame_height);
> >>> +     else
> >>> +             vidcap_get_orig_from_set(frame_width, frame_height);
> >>> +}
> >>> +
> >>> +static int get_visible_format(int fd, unsigned int &width, unsigned int &height) {
> >>> +     int ret = 0;
> >>> +     if(is_m2m_enc) {
> >>> +             struct v4l2_selection in_selection;
> >>> +
> >>> +             in_selection.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
> >>> +             in_selection.target = V4L2_SEL_TGT_CROP;
> >>> +
> >>> +             if ( (ret = ioctl(fd, VIDIOC_G_SELECTION, &in_selection)) != 0) {
> >>> +                     fprintf(stderr,"get_visible_format: error in g_selection ioctl: %d\n",ret);
> >>> +                     return ret;
> >>> +             }
> >>> +             width = in_selection.r.width;
> >>> +             height = in_selection.r.height;
> >>> +     }
> >>> +     else { //TODO - g_selection with COMPOSE should be used here when implemented in driver
> >>> +             vidcap_get_orig_from_set(width, height);
> >>> +     }
> >>> +     return 0;
> >>> +}
> >>> +
> >>> +
> >>>  void fps_timestamps::determine_field(int fd, unsigned type)
> >>>  {
> >>>       struct v4l2_format fmt = { };
> >>> @@ -419,7 +503,6 @@ static void print_buffer(FILE *f, struct v4l2_buffer &buf)
> >>>                       fprintf(f, "\t\tData Offset: %u\n", p->data_offset);
> >>>               }
> >>>       }
> >>> -
> >>>       fprintf(f, "\n");
> >>>  }
> >>>
> >>> @@ -657,7 +740,131 @@ void streaming_cmd(int ch, char *optarg)
> >>>       }
> >>>  }
> >>>
> >>> -static bool fill_buffer_from_file(cv4l_queue &q, cv4l_buffer &b, FILE *fin)
> >>> +bool padding(cv4l_fd &fd, cv4l_queue &q, unsigned char* buf, FILE *fpointer, unsigned &sz, unsigned &len, bool is_read)
> >>
> >> This should definitely be a static function. Also, this is not a very good name.
> >>
> >> Why not call it fill_padded_buffer_from_file()?
> >
> > This function is used both for reading from file for the encoder and
> > writing to file for the decoder.
> > Maybe it can be called read_write_padded_frame ?
>
> That would work.
>
> >
> >>
> >>> +{
> >>> +     cv4l_fmt fmt(q.g_type());
> >>
> >> No need to use q.g_type(). 'cv4l_fmt fmt;' is sufficient.
> >>
> >>> +     fd.g_fmt(fmt, q.g_type());
> >>
> >> After all, it's filled here.
> >>
> >>> +     const struct v4l2_fwht_pixfmt_info *vic_fmt = v4l2_fwht_find_pixfmt(fmt.g_pixelformat());
> >>
> >> This test should be moved to fill_buffer_from_file. If it is not an encoder and
> >> the pixelformat is not known (v4l2_fwht_find_pixfmt() returns NULL), then it should
> >> fallback to the old behavior. So this function should only be called when you have
> >> all the information about the pixelformat.
> >>
> >
> > This function is supposed to be called only for m2m encoder on the
> > output buffer and m2m decoder on the capture buffer
> > so vic_format is not NULL in those case.
>
> Actually, handling padding is not specific to codecs. Any video device can have
> cropping or composing.
>
> The generic rules are:
>
> 1) if a video output device supports TGT_CROP, then use that rectangle when reading
>    from a file.
>
> 2) if a video capture device supports TGT_COMPOSE, then use that rectangle when
>    writing to a file.
>
> The problem with this is that doing this requires v4l2-ctl to understand all the pixelformats.
> That's a lot more work so for now just use v4l2_fwht_find_pixfmt() which has the information
> needed for the most common formats.
>
> Anything not known by v4l2_fwht_find_pixfmt() can just fall back to the old behavior.
>
So I'm not sure what is the correct implementation here,
Currently this function suppose to be used only by m2m_enc/dec, I
actually have no idea
how other types of drivers work. What exactly should be the conditions
for calling this function ?

Dafna

> >
> >>> +     unsigned coded_width = fmt.g_width();
> >>> +     unsigned coded_height = fmt.g_height();
> >>> +     unsigned real_width;
> >>> +     unsigned real_height;
> >>> +     unsigned char *buf_p = (unsigned char*) buf;
> >>> +
> >>> +     if(is_read) {
> >>> +             real_width  = frame_width;
> >>> +             real_height = frame_height;
> >>> +     }
> >>> +     else {
> >>> +             real_width  = visible_width;
> >>> +             real_height = visible_height;
> >>> +     }
> >>> +     sz = 0;
> >>> +     len = real_width * real_height * vic_fmt->sizeimage_mult / vic_fmt->sizeimage_div;
> >>> +     switch(vic_fmt->id) {
> >>> +     case V4L2_PIX_FMT_YUYV:
> >>> +     case V4L2_PIX_FMT_YVYU:
> >>> +     case V4L2_PIX_FMT_UYVY:
> >>> +     case V4L2_PIX_FMT_VYUY:
> >>> +     case V4L2_PIX_FMT_RGB24:
> >>> +     case V4L2_PIX_FMT_HSV24:
> >>> +     case V4L2_PIX_FMT_BGR24:
> >>> +     case V4L2_PIX_FMT_RGB32:
> >>> +     case V4L2_PIX_FMT_XRGB32:
> >>> +     case V4L2_PIX_FMT_HSV32:
> >>> +     case V4L2_PIX_FMT_BGR32:
> >>> +     case V4L2_PIX_FMT_XBGR32:
> >>> +     case V4L2_PIX_FMT_ARGB32:
> >>> +     case V4L2_PIX_FMT_ABGR32:
> >>
> >> I'd put this all under a 'default' case. I think GREY can also be added here.
> >>
> >> What I would really like to see is that only the information from v4l2_fwht_pixfmt_info
> >> can be used here without requiring a switch.
> >>
> >> I think all that is needed to do that is that struct v4l2_fwht_pixfmt_info is extended
> >> with a 'planes_num' field, which is 1 for interleaved formats, 2 for luma/interleaved chroma
> >> planar formats and 3 for luma/cr/cb planar formats.
> >>
> > So I should send a patch to the kernel code, adding this field ?
>
> Yes.
>
> >
> >>> +             for(unsigned i=0; i < real_height; i++) {
> >>> +                     unsigned int consume_sz = vic_fmt->bytesperline_mult*real_width;
> >>> +                     unsigned int wsz = 0;
> >>> +                     if(is_read)
> >>> +                             wsz = fread(buf_p, 1, consume_sz, fpointer);
> >>> +                     else
> >>> +                             wsz = fwrite(buf_p, 1, consume_sz, fpointer);
> >>> +                     sz += wsz;
> >>> +                     if(wsz == 0 && i == 0)
> >>> +                             break;
> >>> +                     if(wsz != consume_sz) {
> >>> +                             fprintf(stderr, "padding: needed %u bytes, got %u\n",consume_sz, wsz);
> >>> +                             return false;
> >>> +                     }
> >>> +                     buf_p += vic_fmt->chroma_step*coded_width;
> >>> +             }
> >>> +     break;
> >>> +
> >>> +     case V4L2_PIX_FMT_NV12:
> >>> +     case V4L2_PIX_FMT_NV16:
> >>> +     case V4L2_PIX_FMT_NV24:
> >>> +     case V4L2_PIX_FMT_NV21:
> >>> +     case V4L2_PIX_FMT_NV61:
> >>> +     case V4L2_PIX_FMT_NV42:
> >>> +             for(unsigned plane_idx = 0; plane_idx < 2; plane_idx++) {
> >>> +                     unsigned h_div = (plane_idx == 0) ? 1 : vic_fmt->height_div;
> >>> +                     unsigned w_div = (plane_idx == 0) ? 1 : vic_fmt->width_div;
> >>> +                     unsigned step  =  (plane_idx == 0) ? vic_fmt->luma_alpha_step : vic_fmt->chroma_step;
> >>> +
> >>> +                     for(unsigned i=0; i <  real_height/h_div; i++) {
> >>> +                             unsigned int wsz = 0;
> >>> +                             unsigned int consume_sz = step * real_width / w_div;
> >>> +                             if(is_read)
> >>> +                                     wsz = fread(buf_p, 1,  consume_sz, fpointer);
> >>> +                             else
> >>> +                                     wsz = fwrite(buf_p, 1, consume_sz, fpointer);
> >>> +                             if(wsz == 0 && i == 0 && plane_idx == 0)
> >>> +                                     break;
> >>> +                             if(wsz != consume_sz) {
> >>> +                                     fprintf(stderr, "padding: needed %u bytes, got %u\n",consume_sz, wsz);
> >>> +                                     return true;
> >>> +                             }
> >>> +                             sz += wsz;
> >>> +                             buf_p += step*coded_width/w_div;
> >>> +                     }
> >>> +                     buf_p += (coded_width / w_div) * (coded_height - real_height) / h_div;
> >>> +
> >>> +                     if(sz == 0)
> >>> +                             break;
> >>> +             }
> >>> +     break;
> >>> +     case V4L2_PIX_FMT_YUV420:
> >>> +     case V4L2_PIX_FMT_YUV422P:
> >>> +     case V4L2_PIX_FMT_YVU420:
> >>> +     case V4L2_PIX_FMT_GREY:
> >>> +             for(unsigned comp_idx = 0; comp_idx < vic_fmt->components_num; comp_idx++) {
> >>> +                     unsigned h_div = (comp_idx == 0) ? 1 : vic_fmt->height_div;
> >>> +                     unsigned w_div = (comp_idx == 0) ? 1 : vic_fmt->width_div;
> >>> +
> >>> +                     for(unsigned i=0; i < real_height/h_div; i++) {
> >>> +                             unsigned int wsz = 0;
> >>> +                             unsigned int consume_sz = real_width/w_div;
> >>> +                             if(is_read)
> >>> +                                     wsz = fread(buf_p, 1, consume_sz, fpointer);
> >>> +                             else
> >>> +                                     wsz = fwrite(buf_p, 1, consume_sz, fpointer);
> >>> +                             if(wsz == 0 && i == 0 && comp_idx == 0)
> >>> +                                     break;
> >>> +                             if(wsz != consume_sz) {
> >>> +                                     fprintf(stderr, "padding: needed %u bytes, got %u\n",consume_sz, wsz);
> >>> +                                     return true;
> >>> +                             }
> >>> +                             sz += wsz;
> >>> +                             buf_p += coded_width/w_div;
> >>> +                     }
> >>> +                     buf_p += (coded_width / w_div) * (coded_height - real_height) / h_div;
> >>> +
> >>> +                     if(sz == 0)
> >>> +                             break;
> >>> +             }
> >>> +             break;
> >>> +     default:
> >>> +             fprintf(stderr,"the format is not supported yet\n");
> >>> +             return false;
> >>> +     }
> >>> +     return true;
> >>> +}
> >>> +
> >>> +static bool fill_buffer_from_file(cv4l_fd &fd, cv4l_queue &q, cv4l_buffer &b, FILE *fin)
> >>>  {
> >>>       static bool first = true;
> >>>       static bool is_fwht = false;
> >>> @@ -785,7 +992,15 @@ restart:
> >>>                               return false;
> >>>                       }
> >>>               }
> >>> -             sz = fread(buf, 1, len, fin);
> >>> +
> >>> +             if(is_m2m_enc) {
> >>> +                     if(!padding(fd, q, (unsigned char*) buf, fin, sz, len, true))
> >>> +                             return false;
> >>> +             }
> >>> +             else {
> >>> +                     sz = fread(buf, 1, len, fin);
> >>> +             }
> >>> +
> >>>               if (first && sz != len) {
> >>>                       fprintf(stderr, "Insufficient data\n");
> >>>                       return false;
> >>> @@ -908,7 +1123,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(q, buf, fin))
> >>> +             if (fin && !fill_buffer_from_file(fd, q, buf, fin))
> >>>                       return -2;
> >>>
> >>>               if (qbuf) {
> >>> @@ -960,7 +1175,7 @@ static int do_handle_cap(cv4l_fd &fd, cv4l_queue &q, FILE *fout, int *index,
> >>>               if (fd.qbuf(buf))
> >>>                       return -1;
> >>>       }
> >>> -
> >>> +
> >>
> >> Seems to be a whitespace only change, just drop this change.
> >>
> >>>       double ts_secs = buf.g_timestamp().tv_sec + buf.g_timestamp().tv_usec / 1000000.0;
> >>>       fps_ts.add_ts(ts_secs, buf.g_sequence(), buf.g_field());
> >>>
> >>> @@ -1023,8 +1238,15 @@ static int do_handle_cap(cv4l_fd &fd, cv4l_queue &q, FILE *fout, int *index,
> >>>                       }
> >>>                       if (host_fd_to >= 0)
> >>>                               sz = fwrite(comp_ptr[j] + offset, 1, used, fout);
> >>> -                     else
> >>> -                             sz = fwrite((u8 *)q.g_dataptr(buf.g_index(), j) + offset, 1, used, fout);
> >>> +                     else {
> >>> +                             if(!is_m2m_enc) {
> >>> +                                     if(!padding(fd, q, (u8 *)q.g_dataptr(buf.g_index(), j) + offset, fout, sz, used, false))
> >>> +                                             return false;
> >>> +                             }
> >>> +                             else {
> >>> +                                     sz = fwrite((u8 *)q.g_dataptr(buf.g_index(), j) + offset, 1, used, fout);
> >>> +                             }
> >>> +                     }
> >>
> >> This doesn't feel right.
> >>
> >> I think a write_buffer_to_file() function should be introduced that deals with these
> >> variations.
> >
> > Not sure what you meant, should I implement this if-else in another function ?
> > The "padding" function is used both for reading and writing to/from
> > padded buffer.
> > The condition for calling it here should be changed to
> > "if(is_m2m_dec)" in which case "padding" will
> > write a raw frame to a file from the padded capture buffer.
>
> static void write_buffer_to_file(cv4l_queue &q, cv4l_buffer &b, FILE *fout)
> {
> #ifndef NO_STREAM_TO
>         // code
> #endif
> }
>
> And in do_handle_cap() drop the NO_STREAM_TO and replace it with a call
> to the new function:
>
>         if (fout && (!stream_skip || ignore_count_skip) &&
>             buf.g_bytesused(0) && !(buf.g_flags() & V4L2_BUF_FLAG_ERROR))
>                 write_buffer_to_file(q, buf, fout);
>
> This can be done in a separate patch: first refactor the code, introducing the
> new function, then add support for handling padding.
>
> >
> >>
> >>>
> >>>                       if (sz != used)
> >>>                               fprintf(stderr, "%u != %u\n", sz, used);
> >>> @@ -1130,7 +1352,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(q, buf, fin))
> >>> +     if (fin && !fill_buffer_from_file(fd, q, buf, fin))
> >>>               return -2;
> >>>
> >>>       if (!fin && stream_out_refresh) {
> >>> @@ -1227,7 +1449,7 @@ static void streaming_set_cap(cv4l_fd &fd)
> >>>               }
> >>>               break;
> >>>       }
> >>> -
> >>> +
> >>>       memset(&sub, 0, sizeof(sub));
> >>>       sub.type = V4L2_EVENT_EOS;
> >>>       fd.subscribe_event(sub);
> >>> @@ -2031,6 +2253,21 @@ void streaming_set(cv4l_fd &fd, cv4l_fd &out_fd)
> >>>       int do_cap = options[OptStreamMmap] + options[OptStreamUser] + options[OptStreamDmaBuf];
> >>>       int do_out = options[OptStreamOutMmap] + options[OptStreamOutUser] + options[OptStreamOutDmaBuf];
> >>>
> >>> +     int r = get_codec_type(fd.g_fd(), is_m2m_enc);
> >>> +     if(r) {
> >>> +             fprintf(stderr, "error checking codec type\n");
> >>> +             return;
> >>> +     }
> >>> +
> >>> +     r = get_visible_format(fd.g_fd(), visible_width, visible_height);
> >>> +
> >>> +     if(r) {
> >>> +             fprintf(stderr, "error getting the visible width\n");
> >>> +             return;
> >>> +     }
> >>> +
> >>> +     get_frame_dims(frame_width, frame_height);
> >>> +
> >>>       if (out_fd.g_fd() < 0) {
> >>>               out_capabilities = capabilities;
> >>>               out_priv_magic = priv_magic;
> >>> diff --git a/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp b/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp
> >>> index dc17a868..932f1fd2 100644
> >>> --- a/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp
> >>> +++ b/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp
> >>> @@ -244,6 +244,12 @@ void vidcap_get(cv4l_fd &fd)
> >>>       }
> >>>  }
> >>>
> >>> +void vidcap_get_orig_from_set(unsigned int &r_width, unsigned int &r_height) {
> >>> +     r_height = height;
> >>> +     r_width = width;
> >>> +}
> >>> +
> >>> +
> >>>  void vidcap_list(cv4l_fd &fd)
> >>>  {
> >>>       if (options[OptListFormats]) {
> >>> diff --git a/utils/v4l2-ctl/v4l2-ctl-vidout.cpp b/utils/v4l2-ctl/v4l2-ctl-vidout.cpp
> >>> index 5823df9c..05bd43ed 100644
> >>> --- a/utils/v4l2-ctl/v4l2-ctl-vidout.cpp
> >>> +++ b/utils/v4l2-ctl/v4l2-ctl-vidout.cpp
> >>> @@ -208,6 +208,11 @@ void vidout_get(cv4l_fd &fd)
> >>>       }
> >>>  }
> >>>
> >>> +void vidout_get_orig_from_set(unsigned int &r_width, unsigned int &r_height) {
> >>> +     r_height = height;
> >>> +     r_width = width;
> >>> +}
> >>
> >> Don't do this (same for vidcap_get_orig_from_set).
> >>
> >> I think you just want to get the width and height from VIDIOC_G_FMT here,
> >> so why not just call that?
> >>
> > Those width/height are the values that are given by the user command.
>
> Yes, but those values are used in ioctl calls to the driver, so rather
> than using those values you query the driver.
>
> > They are needed in order to
> > read raw frames line by line for the encoder.
>
> Why not call G_FMT and G_SELECTION(TGT_CROP) to obtain that information?
>
> Please note that all the set and get options are all processed before the
> streaming options. So when you start streaming the driver is fully configured.
>
> > Maybe I can implement it by calling 'parse_fmt' in 'stream_cmd'
> > function similar to how 'vidout_cmd' do it.
> >
> > https://git.linuxtv.org/v4l-utils.git/tree/utils/v4l2-ctl/v4l2-ctl-vidout.cpp#n90
> >
> >
> >> Remember that you can call v4l2-ctl without setting the output width and height
> >> if the defaults that the driver sets are already fine. In that case the width and height
> >> variables in this source are just 0.
> >>
> >>> +
> >>>  void vidout_list(cv4l_fd &fd)
> >>>  {
> >>>       if (options[OptListOutFormats]) {
> >>> diff --git a/utils/v4l2-ctl/v4l2-ctl.h b/utils/v4l2-ctl/v4l2-ctl.h
> >>> index 5a52a0a4..ab2994b2 100644
> >>> --- a/utils/v4l2-ctl/v4l2-ctl.h
> >>> +++ b/utils/v4l2-ctl/v4l2-ctl.h
> >>> @@ -357,6 +357,8 @@ void vidout_cmd(int ch, char *optarg);
> >>>  void vidout_set(cv4l_fd &fd);
> >>>  void vidout_get(cv4l_fd &fd);
> >>>  void vidout_list(cv4l_fd &fd);
> >>> +void vidcap_get_orig_from_set(unsigned int &r_width, unsigned int &r_height);
> >>> +void vidout_get_orig_from_set(unsigned int &r_width, unsigned int &r_height);
> >>>
> >>>  // v4l2-ctl-overlay.cpp
> >>>  void overlay_usage(void);
> >>>
> >>
> >> This patch needs more work (not surprisingly, since it takes a bit of time to
> >> understand the v4l2-ctl source code).
> >>
> >> Please stick to the kernel coding style! Using a different style makes it harder
> >> for me to review since my pattern matches routines in my brain no longer work
> >> optimally. It's like reading text with spelling mistakes, you cn stil undrstant iT,
> >> but it tekes moore teem. :-)
> >>
> > okei :)
> >
> >> Regards,
> >>
> >>         Hans
>
> Regards,
>
>         Hans



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux