Fwd: [PATCH] media: vicodec: add support for CROP selection

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

 



---------- Forwarded message ---------
From: Dafna Hirschfeld <dafna3@xxxxxxxxx>
Date: Mon, Dec 17, 2018 at 7:23 PM
Subject: Re: [PATCH] media: vicodec: add support for CROP selection
To: Hans Verkuil <hverkuil@xxxxxxxxx>
Cc: Linux Media Mailing List <linux-media@xxxxxxxxxxxxxxx>,
<helen.koike@xxxxxxxxxxxxx>




On Sun, Dec 16, 2018 at 2:24 PM Hans Verkuil <hverkuil@xxxxxxxxx> wrote:
>
> On 12/15/18 12:54 PM, Dafna Hirschfeld wrote:
> > Add support for the selection api for the crop target.
>
> Mention that this is added for the encoder only.
>
> > The driver rounds up the width and height such that
> > all planes dimesnsions are multiple of 8.
>
> dimesnsions -> dimensions
>
> > The userspace client should also read and write
> > the raw frames according the padding.
>
> Since we're not changing the userspace client here, you can drop
> that paragraph.
>
> >
> > Signed-off-by: Dafna Hirschfeld <dafna3@xxxxxxxxx>
> > ---
> >  drivers/media/platform/vicodec/codec-fwht.c   |  45 ++--
> >  drivers/media/platform/vicodec/codec-fwht.h   |   5 +-
> >  .../media/platform/vicodec/codec-v4l2-fwht.c  |  18 +-
> >  .../media/platform/vicodec/codec-v4l2-fwht.h  |   2 +
> >  drivers/media/platform/vicodec/vicodec-core.c | 219 ++++++++++++++----
> >  5 files changed, 213 insertions(+), 76 deletions(-)
> >
> > diff --git a/drivers/media/platform/vicodec/codec-fwht.c b/drivers/media/platform/vicodec/codec-fwht.c
> > index a678a716580c..ab59f34e9818 100644
> > --- a/drivers/media/platform/vicodec/codec-fwht.c
> > +++ b/drivers/media/platform/vicodec/codec-fwht.c
> > @@ -659,7 +659,7 @@ static void add_deltas(s16 *deltas, const u8 *ref, int stride)
> >  }
> >
> >  static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max,
> > -                     struct fwht_cframe *cf, u32 height, u32 width,
> > +                     struct fwht_cframe *cf, u32 height, u32 width, u32 stride,
> >                       unsigned int input_step,
> >                       bool is_intra, bool next_is_intra)
> >  {
> > @@ -679,9 +679,9 @@ static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max,
> >
> >                       if (!is_intra)
> >                               blocktype = decide_blocktype(input, refp,
> > -                                     deltablock, width, input_step);
> > +                                     deltablock, stride, input_step);
> >                       if (blocktype == IBLOCK) {
> > -                             fwht(input, cf->coeffs, width, input_step, 1);
> > +                             fwht(input, cf->coeffs, stride, input_step, 1);
> >                               quantize_intra(cf->coeffs, cf->de_coeffs,
> >                                              cf->i_frame_qp);
> >                       } else {
> > @@ -722,7 +722,7 @@ static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max,
> >                       }
> >                       last_size = size;
> >               }
> > -             input += width * 7 * input_step;
> > +             input += (stride - width/8) * 8 * input_step;
>
> width/8 -> width / 8
>
> Hmm, I think this calculation is confusing.
>
> A better solution would be to set the input pointer just before the
> 'for (i = 0; i < width / 8; i++) {' loop. E.g.:
>
>         for (j = 0; j < height / 8; j++) {
>                 input = input_start + j * 8 * stride * input_step;
>                 for (i = 0; i < width / 8; i++) {
>
> (I hope I got the calculation right)
>
> >       }
> >
> >  exit_loop:
> > @@ -756,7 +756,7 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
> >
> >       rlco_max = rlco + size / 2 - 256;
> >       encoding = encode_plane(frm->luma, ref_frm->luma, &rlco, rlco_max, cf,
> > -                             frm->height, frm->width,
> > +                             frm->height, frm->width, frm->stride,
> >                               frm->luma_alpha_step, is_intra, next_is_intra);
> >       if (encoding & FWHT_FRAME_UNENCODED)
> >               encoding |= FWHT_LUMA_UNENCODED;
> > @@ -765,11 +765,12 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
> >       if (frm->components_num >= 3) {
> >               u32 chroma_h = frm->height / frm->height_div;
> >               u32 chroma_w = frm->width / frm->width_div;
> > +             u32 stride = frm->stride / frm->width_div;
>
> Call this chroma_stride to stay consistent with chroma_h/w etc.
>
> >               unsigned int chroma_size = chroma_h * chroma_w;
> >
> >               rlco_max = rlco + chroma_size / 2 - 256;
> >               encoding |= encode_plane(frm->cb, ref_frm->cb, &rlco, rlco_max,
> > -                                      cf, chroma_h, chroma_w,
> > +                                      cf, chroma_h, chroma_w, stride,
> >                                        frm->chroma_step,
> >                                        is_intra, next_is_intra);
> >               if (encoding & FWHT_FRAME_UNENCODED)
> > @@ -777,7 +778,7 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
> >               encoding &= ~FWHT_FRAME_UNENCODED;
> >               rlco_max = rlco + chroma_size / 2 - 256;
> >               encoding |= encode_plane(frm->cr, ref_frm->cr, &rlco, rlco_max,
> > -                                      cf, chroma_h, chroma_w,
> > +                                      cf, chroma_h, chroma_w, stride,
> >                                        frm->chroma_step,
> >                                        is_intra, next_is_intra);
> >               if (encoding & FWHT_FRAME_UNENCODED)
> > @@ -789,7 +790,7 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
> >               rlco_max = rlco + size / 2 - 256;
> >               encoding |= encode_plane(frm->alpha, ref_frm->alpha, &rlco,
> >                                       rlco_max, cf, frm->height, frm->width,
> > -                                     frm->luma_alpha_step,
> > +                                     frm->stride, frm->luma_alpha_step,
> >                                       is_intra, next_is_intra);
> >               if (encoding & FWHT_FRAME_UNENCODED)
> >                       encoding |= FWHT_ALPHA_UNENCODED;
> > @@ -801,7 +802,7 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
> >  }
> >
> >  static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref,
> > -                      u32 height, u32 width, bool uncompressed)
> > +                      u32 height, u32 width, u32 stride, bool uncompressed)
> >  {
> >       unsigned int copies = 0;
> >       s16 copy[8 * 8];
> > @@ -822,13 +823,13 @@ static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref,
> >        */
> >       for (j = 0; j < height / 8; j++) {
> >               for (i = 0; i < width / 8; i++) {
> > -                     u8 *refp = ref + j * 8 * width + i * 8;
> > +                     u8 *refp = ref + j * 8 * stride + i * 8;
> >
> >                       if (copies) {
> >                               memcpy(cf->de_fwht, copy, sizeof(copy));
> >                               if (stat & PFRAME_BIT)
> > -                                     add_deltas(cf->de_fwht, refp, width);
> > -                             fill_decoder_block(refp, cf->de_fwht, width);
> > +                                     add_deltas(cf->de_fwht, refp, stride);
> > +                             fill_decoder_block(refp, cf->de_fwht, stride);
> >                               copies--;
> >                               continue;
> >                       }
> > @@ -847,35 +848,37 @@ static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref,
> >                       if (copies)
> >                               memcpy(copy, cf->de_fwht, sizeof(copy));
> >                       if (stat & PFRAME_BIT)
> > -                             add_deltas(cf->de_fwht, refp, width);
> > -                     fill_decoder_block(refp, cf->de_fwht, width);
> > +                             add_deltas(cf->de_fwht, refp, stride);
> > +                     fill_decoder_block(refp, cf->de_fwht, stride);
> >               }
> >       }
> >  }
> >
> >  void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref,
> > -                    u32 hdr_flags, unsigned int components_num)
> > +                    u32 hdr_flags, unsigned int components_num, unsigned int stride)
> >  {
> >       const __be16 *rlco = cf->rlc_data;
> >
> > -     decode_plane(cf, &rlco, ref->luma, cf->height, cf->width,
> > +     decode_plane(cf, &rlco, ref->luma, cf->height, cf->width, stride,
> >                    hdr_flags & FWHT_FL_LUMA_IS_UNCOMPRESSED);
> >
> >       if (components_num >= 3) {
> >               u32 h = cf->height;
> >               u32 w = cf->width;
> > -
> > +             u32 s = stride;
>
> Add an empty line after declaring the variables.
>
> >               if (!(hdr_flags & FWHT_FL_CHROMA_FULL_HEIGHT))
> >                       h /= 2;
> > -             if (!(hdr_flags & FWHT_FL_CHROMA_FULL_WIDTH))
> > +             if (!(hdr_flags & FWHT_FL_CHROMA_FULL_WIDTH)) {
> >                       w /= 2;
> > -             decode_plane(cf, &rlco, ref->cb, h, w,
> > +                     s /= 2;
> > +             }
> > +             decode_plane(cf, &rlco, ref->cb, h, w, s,
> >                            hdr_flags & FWHT_FL_CB_IS_UNCOMPRESSED);
> > -             decode_plane(cf, &rlco, ref->cr, h, w,
> > +             decode_plane(cf, &rlco, ref->cr, h, w, s,
> >                            hdr_flags & FWHT_FL_CR_IS_UNCOMPRESSED);
> >       }
> >
> >       if (components_num == 4)
> > -             decode_plane(cf, &rlco, ref->alpha, cf->height, cf->width,
> > +             decode_plane(cf, &rlco, ref->alpha, cf->height, cf->width, stride,
> >                            hdr_flags & FWHT_FL_ALPHA_IS_UNCOMPRESSED);
> >  }
> > diff --git a/drivers/media/platform/vicodec/codec-fwht.h b/drivers/media/platform/vicodec/codec-fwht.h
> > index 90ff8962fca7..86c38e873f69 100644
> > --- a/drivers/media/platform/vicodec/codec-fwht.h
> > +++ b/drivers/media/platform/vicodec/codec-fwht.h
> > @@ -81,6 +81,8 @@
> >  #define FWHT_FL_COMPONENTS_NUM_MSK   GENMASK(17, 16)
> >  #define FWHT_FL_COMPONENTS_NUM_OFFSET        16
> >
> > +#define vic_round_dim(dim, div) (round_up(dim / div, 8) * div)
>
> This macro needs a comment explaining what it does.
>
> > +
> >  struct fwht_cframe_hdr {
> >       u32 magic1;
> >       u32 magic2;
> > @@ -112,6 +114,7 @@ struct fwht_raw_frame {
> >       unsigned int luma_alpha_step;
> >       unsigned int chroma_step;
> >       unsigned int components_num;
> > +     unsigned int stride;
> >       u8 *luma, *cb, *cr, *alpha;
> >  };
> >
> > @@ -127,6 +130,6 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
> >                     struct fwht_cframe *cf,
> >                     bool is_intra, bool next_is_intra);
> >  void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref,
> > -                    u32 hdr_flags, unsigned int components_num);
> > +                    u32 hdr_flags, unsigned int components_num, unsigned int stride);
> >
> >  #endif
> > diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.c b/drivers/media/platform/vicodec/codec-v4l2-fwht.c
> > index 8cb0212df67f..3eef6bbe5c06 100644
> > --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.c
> > +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.c
> > @@ -56,7 +56,7 @@ const struct v4l2_fwht_pixfmt_info *v4l2_fwht_get_pixfmt(u32 idx)
> >
> >  int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
> >  {
> > -     unsigned int size = state->width * state->height;
> > +     unsigned int size;
> >       const struct v4l2_fwht_pixfmt_info *info = state->info;
> >       struct fwht_cframe_hdr *p_hdr;
> >       struct fwht_cframe cf;
> > @@ -66,8 +66,11 @@ int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
> >
> >       if (!info)
> >               return -EINVAL;
> > +
> > +     size = state->stride * state->padded_height;
>
> Throughout this patch you talk about 'stride', but I think calling it 'padded_width' is a
> much better name.
>
> There are actually three values here:
>
> width: this is the visible width in pixels
> padded_width: this is the visible width in pixels rounded up to the next macroblock alignment
> stride: this is the distance in bytes between two lines.
>
> width <= padded_width <= stride / input_step
>
Currently q_data->width contain none of those, it is the value set by
the S_FMT request so the stride can be calculated from it.
This is actually also the visible width for the decoder, since the
COMPOSE selection is not implemented yet. Right ?

state->width is the cropped width for the encoder and it is the same
as q_data->width for the decoder.
You think I should change the field name  'state->width' to
'state->visible_width' ?

I think that when I implement the COMPOSE for the decoder I could
change the field ''cropped_width" with "visible_width"
in ""vicodec_q_data" and it will be the cropped width for the encoder
and the composed width for the decoder.
Also, when I implement the COMPOSE for the decoder, then q_data->width
could be changed to q_data->coded_width and
will contain the coded resolution (that is
"vic_round_up(width,info->width_div)")

Dafna



>
> Note: stride corresponds to the bytesperline field in struct v4l2_pix_format.
>
> You still need the stride, but the padded_width can always be calculated from the
> width.
>
> I think you need to go through this patch carefully and use the right terminology.
>
> E.g. in encode_plane() you do need the stride, but the width and height that are
> passed to this function should really be the padded width and height.
>
> You can add a line like this at the start of encode_plane() to verify that you get
> valid values:
>
>         WARN_ON((padded_width & 7) || (padded_height & 7));
>
> >       rf.width = state->width;
> >       rf.height = state->height;
> > +     rf.stride = state->stride;
> >       rf.luma = p_in;
> >       rf.width_div = info->width_div;
> >       rf.height_div = info->height_div;
> > @@ -209,8 +212,8 @@ int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
> >
> >  int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
> >  {
> > -     unsigned int size = state->width * state->height;
> > -     unsigned int chroma_size = size;
> > +     unsigned int size;
> > +     unsigned int chroma_size;
> >       unsigned int i;
> >       u32 flags;
> >       struct fwht_cframe_hdr *p_hdr;
> > @@ -218,10 +221,14 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
> >       u8 *p;
> >       unsigned int components_num = 3;
> >       unsigned int version;
> > +     const struct v4l2_fwht_pixfmt_info *info;
> >
> >       if (!state->info)
> >               return -EINVAL;
> >
> > +     info = state->info;
> > +     size = state->stride * state->padded_height;
> > +     chroma_size = size;
> >       p_hdr = (struct fwht_cframe_hdr *)p_in;
> >       cf.width = ntohl(p_hdr->width);
> >       cf.height = ntohl(p_hdr->height);
> > @@ -234,8 +241,7 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
> >       }
> >
> >       if (p_hdr->magic1 != FWHT_MAGIC1 ||
> > -         p_hdr->magic2 != FWHT_MAGIC2 ||
> > -         (cf.width & 7) || (cf.height & 7))
> > +         p_hdr->magic2 != FWHT_MAGIC2)
> >               return -EINVAL;
> >
> >       /* TODO: support resolution changes */
> > @@ -260,7 +266,7 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
> >       if (!(flags & FWHT_FL_CHROMA_FULL_HEIGHT))
> >               chroma_size /= 2;
> >
> > -     fwht_decode_frame(&cf, &state->ref_frame, flags, components_num);
> > +     fwht_decode_frame(&cf, &state->ref_frame, flags, components_num, state->stride);
> >
> >       /*
> >        * TODO - handle the case where the compressed stream encodes a
> > diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.h b/drivers/media/platform/vicodec/codec-v4l2-fwht.h
> > index ed53e28d4f9c..fa429a7cc4cf 100644
> > --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.h
> > +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.h
> > @@ -25,6 +25,8 @@ struct v4l2_fwht_state {
> >       const struct v4l2_fwht_pixfmt_info *info;
> >       unsigned int width;
> >       unsigned int height;
> > +     unsigned int stride;
> > +     unsigned int padded_height;
> >       unsigned int gop_size;
> >       unsigned int gop_cnt;
> >       u16 i_frame_qp;
> > diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c
> > index 0d7876f5acf0..d593d65869f7 100644
> > --- a/drivers/media/platform/vicodec/vicodec-core.c
> > +++ b/drivers/media/platform/vicodec/vicodec-core.c
> > @@ -77,6 +77,8 @@ static struct platform_device vicodec_pdev = {
> >  struct vicodec_q_data {
> >       unsigned int            width;
> >       unsigned int            height;
> > +     unsigned int            cropped_width;
> > +     unsigned int            cropped_height;
> >       unsigned int            sizeimage;
> >       unsigned int            sequence;
> >       const struct v4l2_fwht_pixfmt_info *info;
> > @@ -464,11 +466,11 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
> >               if (multiplanar)
> >                       return -EINVAL;
> >               pix = &f->fmt.pix;
> > -             pix->width = q_data->width;
> > -             pix->height = q_data->height;
> > +             pix->width = vic_round_dim(q_data->width, info->width_div);
> > +             pix->height = vic_round_dim(q_data->height, info->height_div);
> >               pix->field = V4L2_FIELD_NONE;
> >               pix->pixelformat = info->id;
> > -             pix->bytesperline = q_data->width * info->bytesperline_mult;
> > +             pix->bytesperline = pix->width * info->bytesperline_mult;
> >               pix->sizeimage = q_data->sizeimage;
> >               pix->colorspace = ctx->state.colorspace;
> >               pix->xfer_func = ctx->state.xfer_func;
> > @@ -481,13 +483,13 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
> >               if (!multiplanar)
> >                       return -EINVAL;
> >               pix_mp = &f->fmt.pix_mp;
> > -             pix_mp->width = q_data->width;
> > -             pix_mp->height = q_data->height;
> > +             pix_mp->width = vic_round_dim(q_data->width, info->width_div);
> > +             pix_mp->height = vic_round_dim(q_data->height, info->height_div);
> >               pix_mp->field = V4L2_FIELD_NONE;
> >               pix_mp->pixelformat = info->id;
> >               pix_mp->num_planes = 1;
> >               pix_mp->plane_fmt[0].bytesperline =
> > -                             q_data->width * info->bytesperline_mult;
> > +                             pix_mp->width * info->bytesperline_mult;
> >               pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage;
> >               pix_mp->colorspace = ctx->state.colorspace;
> >               pix_mp->xfer_func = ctx->state.xfer_func;
> > @@ -528,8 +530,8 @@ static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
> >               pix = &f->fmt.pix;
> >               if (pix->pixelformat != V4L2_PIX_FMT_FWHT)
> >                       info = find_fmt(pix->pixelformat);
> > -             pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH) & ~7;
> > -             pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT) & ~7;
> > +             pix->width = vic_round_dim(clamp(pix->width, MIN_WIDTH, MAX_WIDTH), info->width_div);
> > +             pix->height = vic_round_dim(clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT), info->height_div);
> >               pix->field = V4L2_FIELD_NONE;
> >               pix->bytesperline =
> >                       pix->width * info->bytesperline_mult;
> > @@ -545,9 +547,8 @@ static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
> >               if (pix_mp->pixelformat != V4L2_PIX_FMT_FWHT)
> >                       info = find_fmt(pix_mp->pixelformat);
> >               pix_mp->num_planes = 1;
> > -             pix_mp->width = clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH) & ~7;
> > -             pix_mp->height =
> > -                     clamp(pix_mp->height, MIN_HEIGHT, MAX_HEIGHT) & ~7;
> > +             pix_mp->width = vic_round_dim(clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH), info->width_div);
> > +             pix_mp->height = vic_round_dim(clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT), info->height_div);
> >               pix_mp->field = V4L2_FIELD_NONE;
> >               plane->bytesperline =
> >                       pix_mp->width * info->bytesperline_mult;
> > @@ -635,13 +636,14 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
> >       return vidioc_try_fmt(ctx, f);
> >  }
> >
> > -static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
> > +static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f, unsigned int orig_width, unsigned int orig_height)
> >  {
> >       struct vicodec_q_data *q_data;
> >       struct vb2_queue *vq;
> >       bool fmt_changed = true;
> >       struct v4l2_pix_format_mplane *pix_mp;
> >       struct v4l2_pix_format *pix;
> > +     const struct v4l2_fwht_pixfmt_info *info;
> >
> >       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
> >       if (!vq)
> > @@ -650,6 +652,7 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
> >       q_data = get_q_data(ctx, f->type);
> >       if (!q_data)
> >               return -EINVAL;
> > +     info = q_data->info;
> >
> >       switch (f->type) {
> >       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
> > @@ -658,8 +661,8 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
> >               if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
> >                       fmt_changed =
> >                               q_data->info->id != pix->pixelformat ||
> > -                             q_data->width != pix->width ||
> > -                             q_data->height != pix->height;
> > +                             vic_round_dim(q_data->width, info->width_div) != pix->width ||
> > +                             vic_round_dim(q_data->height, info->height_div) != pix->height;
> >
> >               if (vb2_is_busy(vq) && fmt_changed)
> >                       return -EBUSY;
> > @@ -668,8 +671,13 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
> >                       q_data->info = &pixfmt_fwht;
> >               else
> >                       q_data->info = find_fmt(pix->pixelformat);
> > -             q_data->width = pix->width;
> > -             q_data->height = pix->height;
> > +
> > +             q_data->width = orig_width;
> > +             if (q_data->cropped_width > orig_width)
> > +                     q_data->cropped_width = orig_width;
> > +             q_data->height = orig_height;
> > +             if (q_data->cropped_height > orig_height)
> > +                     q_data->cropped_height = orig_height;
> >               q_data->sizeimage = pix->sizeimage;
> >               break;
> >       case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> > @@ -678,8 +686,8 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
> >               if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
> >                       fmt_changed =
> >                               q_data->info->id != pix_mp->pixelformat ||
> > -                             q_data->width != pix_mp->width ||
> > -                             q_data->height != pix_mp->height;
> > +                             vic_round_dim(q_data->width, info->width_div) != pix_mp->width ||
> > +                             vic_round_dim(q_data->height, info->height_div) != pix_mp->height;
> >
> >               if (vb2_is_busy(vq) && fmt_changed)
> >                       return -EBUSY;
> > @@ -688,8 +696,8 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
> >                       q_data->info = &pixfmt_fwht;
> >               else
> >                       q_data->info = find_fmt(pix_mp->pixelformat);
> > -             q_data->width = pix_mp->width;
> > -             q_data->height = pix_mp->height;
> > +             q_data->width = orig_width;
> > +             q_data->height = orig_height;
> >               q_data->sizeimage = pix_mp->plane_fmt[0].sizeimage;
> >               break;
> >       default:
> > @@ -707,12 +715,27 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
> >                               struct v4l2_format *f)
> >  {
> >       int ret;
> > +     unsigned int orig_width, orig_height;
> >
> > +     switch (f->type) {
> > +     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
> > +     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
> > +             orig_width = f->fmt.pix.width;
> > +             orig_height = f->fmt.pix.height;
> > +             break;
> > +     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> > +     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> > +             orig_width = f->fmt.pix_mp.width;
> > +             orig_height = f->fmt.pix_mp.height;
> > +             break;
> > +     default:
> > +             break;
> > +     }
> >       ret = vidioc_try_fmt_vid_cap(file, priv, f);
> >       if (ret)
> >               return ret;
> >
> > -     return vidioc_s_fmt(file2ctx(file), f);
> > +     return vidioc_s_fmt(file2ctx(file), f, orig_width, orig_height);
> >  }
> >
> >  static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
> > @@ -721,36 +744,126 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
> >       struct vicodec_ctx *ctx = file2ctx(file);
> >       struct v4l2_pix_format_mplane *pix_mp;
> >       struct v4l2_pix_format *pix;
> > +     unsigned int orig_width, orig_height;
> >       int ret;
> >
> > -     ret = vidioc_try_fmt_vid_out(file, priv, f);
> > -     if (ret)
> > -             return ret;
> > +     switch (f->type) {
> > +     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
> > +     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
> > +                             pix = &f->fmt.pix;
> > +             orig_width = pix->width;
> > +             orig_height = pix->height;
> > +             ret = vidioc_try_fmt_vid_out(file, priv, f);
> > +             if (ret)
> > +                     return ret;
> > +             ret = vidioc_s_fmt(file2ctx(file), f, orig_width, orig_height);
> > +             if (ret)
> > +                     return ret;
> > +             ctx->state.colorspace = pix->colorspace;
> > +             ctx->state.xfer_func = pix->xfer_func;
> > +             ctx->state.ycbcr_enc = pix->ycbcr_enc;
> > +             ctx->state.quantization = pix->quantization;
> > +             break;
> > +     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> > +     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> > +             pix_mp = &f->fmt.pix_mp;
> > +             orig_width = pix_mp->width;
> > +             orig_height = pix_mp->height;
> > +             ret = vidioc_try_fmt_vid_out(file, priv, f);
> > +             if (ret)
> > +                     return ret;
> > +             ret = vidioc_s_fmt(file2ctx(file), f, orig_width, orig_height);
> > +             if (ret)
> > +                     return ret;
> > +             ctx->state.colorspace = pix_mp->colorspace;
> > +             ctx->state.xfer_func = pix_mp->xfer_func;
> > +             ctx->state.ycbcr_enc = pix_mp->ycbcr_enc;
> > +             ctx->state.quantization = pix_mp->quantization;
> > +             break;
> > +     default:
> > +             break;
> > +     }
> > +     return ret;
> > +}
> >
> > -     ret = vidioc_s_fmt(file2ctx(file), f);
> > -     if (!ret) {
> > -             switch (f->type) {
> > -             case V4L2_BUF_TYPE_VIDEO_CAPTURE:
> > -             case V4L2_BUF_TYPE_VIDEO_OUTPUT:
> > -                     pix = &f->fmt.pix;
> > -                     ctx->state.colorspace = pix->colorspace;
> > -                     ctx->state.xfer_func = pix->xfer_func;
> > -                     ctx->state.ycbcr_enc = pix->ycbcr_enc;
> > -                     ctx->state.quantization = pix->quantization;
> > -                     break;
> > -             case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> > -             case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> > -                     pix_mp = &f->fmt.pix_mp;
> > -                     ctx->state.colorspace = pix_mp->colorspace;
> > -                     ctx->state.xfer_func = pix_mp->xfer_func;
> > -                     ctx->state.ycbcr_enc = pix_mp->ycbcr_enc;
> > -                     ctx->state.quantization = pix_mp->quantization;
> > -                     break;
> > +static int vidioc_g_selection(struct file *file, void *priv,
> > +                         struct v4l2_selection *s)
> > +{
> > +
> > +     struct vicodec_ctx *ctx = file2ctx(file);
> > +     struct vicodec_q_data *q_data;
> > +
> > +     q_data = get_q_data(ctx, s->type);
> > +     if (!q_data)
> > +             return -EINVAL;
> > +
> > +     /* encoder supports only cropping on the OUTPUT buffer */
> > +     if (ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
> > +
> > +             switch (s->target) {
> > +             case V4L2_SEL_TGT_CROP_DEFAULT:
> > +             case V4L2_SEL_TGT_CROP_BOUNDS:
> > +                     s->r.left = s->r.top = 0;
> > +                     s->r.width = q_data->width;
> > +                     s->r.height = q_data->height;
> > +                     return 0;
> > +             case V4L2_SEL_TGT_CROP:
> > +                     s->r.left = s->r.top = 0;
> > +                     s->r.width = q_data->cropped_width;
> > +                     s->r.height = q_data->cropped_height;
> > +                     return 0;
> >               default:
> > -                     break;
> > +                     return -EINVAL;
> > +             }
> > +     /* decoder supports only composing on the CAPTURE buffer */
> > +     } else if (!ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
> > +
> > +             switch (s->target) {
> > +             case V4L2_SEL_TGT_COMPOSE_BOUNDS:
> > +                     s->r.left = s->r.top = 0;
> > +                     s->r.width = q_data->width;
> > +                     s->r.height = q_data->height;
> > +                     return 0;
> > +     /* TODO
> > +             case V4L2_SEL_TGT_COMPOSE:
> > +             case V4L2_SEL_TGT_COMPOSE_DEFAULT:
> > +     */
>
> I would for now add these two as well. They would just return the same as
> COMPOSE_BOUNDS.
>
> > +             default:
> > +                     return -EINVAL;
> >               }
> >       }
> > -     return ret;
> > +     return -EINVAL;
> > +}
> > +
> > +static int vidioc_s_selection(struct file *file, void *priv,
> > +                         struct v4l2_selection *s)
> > +{
> > +
> > +     struct vicodec_ctx *ctx = file2ctx(file);
> > +     struct vicodec_q_data *q_data;
> > +
> > +     q_data = get_q_data(ctx, s->type);
> > +     if (!q_data)
> > +             return -EINVAL;
> > +
> > +     /* encoder supports only cropping on the OUTPUT buffer */
> > +     if (ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
> > +             switch (s->target) {
> > +             case V4L2_SEL_TGT_CROP:
> > +                     s->r.left = s->r.top = 0;
> > +                     q_data->cropped_width = clamp(s->r.width, MIN_WIDTH, q_data->width);
> > +                     s->r.width = q_data->cropped_width;
> > +                     q_data->cropped_height = clamp(s->r.height, MIN_HEIGHT, q_data->height);
> > +                     s->r.height = q_data->cropped_height;
> > +                     return 0;
> > +             default:
> > +                     return -EINVAL;
> > +             }
> > +     /* decoder supports only composing on the CAPTURE buffer */
> > +     } else if (!ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
> > +             /* TODO */
>
> Here too: the COMPOSE rectangle is just overridden with the COMPOSE_BOUNDS
> value (i.e. ignoring what userspace provides).
>
> The TODO is then that you actually should be able to change the COMPOSE
> target.
>
> > +     }
> > +     return -EINVAL;
> >  }
> >
> >  static void vicodec_mark_last_buf(struct vicodec_ctx *ctx)
> > @@ -895,6 +1008,9 @@ static const struct v4l2_ioctl_ops vicodec_ioctl_ops = {
> >       .vidioc_streamon        = v4l2_m2m_ioctl_streamon,
> >       .vidioc_streamoff       = v4l2_m2m_ioctl_streamoff,
> >
> > +     .vidioc_g_selection     = vidioc_g_selection,
> > +     .vidioc_s_selection     = vidioc_s_selection,
> > +
> >       .vidioc_try_encoder_cmd = vicodec_try_encoder_cmd,
> >       .vidioc_encoder_cmd     = vicodec_encoder_cmd,
> >       .vidioc_try_decoder_cmd = vicodec_try_decoder_cmd,
> > @@ -988,8 +1104,8 @@ static int vicodec_start_streaming(struct vb2_queue *q,
> >       struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
> >       struct vicodec_q_data *q_data = get_q_data(ctx, q->type);
> >       struct v4l2_fwht_state *state = &ctx->state;
> > -     unsigned int size = q_data->width * q_data->height;
> >       const struct v4l2_fwht_pixfmt_info *info = q_data->info;
> > +     unsigned int size = vic_round_dim(q_data->width, info->width_div) * vic_round_dim(q_data->height, info->height_div);
>
> Break up this line, it's way too long. A newline after the * will work well.
>
> >       unsigned int chroma_div = info->width_div * info->height_div;
> >       unsigned int total_planes_size;
> >
> > @@ -1010,13 +1126,18 @@ static int vicodec_start_streaming(struct vb2_queue *q,
> >               if (!ctx->is_enc) {
> >                       state->width = q_data->width;
> >                       state->height = q_data->height;
> > +                     state->stride = vic_round_dim(q_data->width, info->width_div);
> > +                     state->padded_height = vic_round_dim(q_data->height, info->height_div);
> > +
> >               }
> >               return 0;
> >       }
> >
> >       if (ctx->is_enc) {
> > -             state->width = q_data->width;
> > -             state->height = q_data->height;
> > +             state->width = q_data->cropped_width;
> > +             state->height = q_data->cropped_height;
> > +             state->stride = vic_round_dim(q_data->width, info->width_div);
> > +             state->padded_height = vic_round_dim(q_data->height, info->height_div);
> >       }
> >       state->ref_frame.width = state->ref_frame.height = 0;
> >       state->ref_frame.luma = kvmalloc(total_planes_size, GFP_KERNEL);
> > @@ -1206,6 +1327,8 @@ static int vicodec_open(struct file *file)
> >               ctx->is_enc ? v4l2_fwht_get_pixfmt(0) : &pixfmt_fwht;
> >       ctx->q_data[V4L2_M2M_SRC].width = 1280;
> >       ctx->q_data[V4L2_M2M_SRC].height = 720;
> > +     ctx->q_data[V4L2_M2M_SRC].cropped_width = 1280;
> > +     ctx->q_data[V4L2_M2M_SRC].cropped_height = 720;
> >       size = 1280 * 720 * ctx->q_data[V4L2_M2M_SRC].info->sizeimage_mult /
> >               ctx->q_data[V4L2_M2M_SRC].info->sizeimage_div;
> >       if (ctx->is_enc)
> >
>
> The main thing that needs to be changed is terminology: make it clear when you are
> talking about the width/height, padded_width/height or stride by choosing the right
> variable names.
>
> 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