public inbox for linux-rockchip@lists.infradead.org
 help / color / mirror / Atom feed
From: Nicolas Dufresne <nicolas.dufresne@collabora.com>
To: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>,
	Sebastian Fricke <sebastian.fricke@collabora.com>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	linux-media@vger.kernel.org,  linux-kernel@vger.kernel.org,
	linux-rockchip@lists.infradead.org,
	 linux-staging@lists.linux.dev, Jonas Karlman <jonas@kwiboo.se>,
	Alex Bee <knaerzche@gmail.com>,
	Collabora Kernel-domain <kernel@collabora.com>,
	 Robert Beckett <bob.beckett@collabora.com>,
	Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	Andrzej Pietrasiewicz <andrzej.p@collabora.com>,
	Benjamin Gaignard <benjamin.gaignard@collabora.com>
Subject: Re: [PATCH v2 09/12] staging: media: rkvdec: h264: Add callbacks for h264
Date: Thu, 12 Jan 2023 16:58:58 -0500	[thread overview]
Message-ID: <b0aca760a1c804d68cd95357b8adcafef0e78b25.camel@collabora.com> (raw)
In-Reply-To: <CAAEAJfDkTX=EwDCs+uN0bFwMb_JhJfkQiwRR9+b-9v3cJnPTsw@mail.gmail.com>

Le jeudi 12 janvier 2023 à 12:21 -0300, Ezequiel Garcia a écrit :
> On Thu, Jan 12, 2023 at 9:56 AM Sebastian Fricke
> <sebastian.fricke@collabora.com> wrote:
> > 
> > Implement the valid format and sps validation callbacks for H264.
> > H264 already has a SPS validation function, adjust it to fit the
> > function the declaration and add error messages.
> > Additionally, add a function to fetch attributes from the SPS in a human
> > readable format to make the code more self documenting.
> > 
> > Signed-off-by: Sebastian Fricke <sebastian.fricke@collabora.com>
> > ---
> >  drivers/staging/media/rkvdec/rkvdec-h264.c | 105 ++++++++++++++++++++++-------
> >  1 file changed, 80 insertions(+), 25 deletions(-)
> > 
> > diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
> > index 4fc167b42cf0..17b215874ddd 100644
> > --- a/drivers/staging/media/rkvdec/rkvdec-h264.c
> > +++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
> > @@ -1026,40 +1026,80 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx,
> >         return 0;
> >  }
> > 
> > -static int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx,
> > -                                   const struct v4l2_ctrl_h264_sps *sps)
> > +/*
> > + * Convert some fields from the SPS structure into human readable attributes.
> > + */
> > +static int rkvdec_h264_get_sps_attributes(struct rkvdec_ctx *ctx, void *sps,
> > +                                         struct sps_attributes *attributes)
> > +{
> > +       struct v4l2_ctrl_h264_sps *h264_sps = sps;
> > +       unsigned int width = (h264_sps->pic_width_in_mbs_minus1 + 1) * 16;
> > +       unsigned int height = (h264_sps->pic_height_in_map_units_minus1 + 1) * 16;
> > +       /*
> > +        * When frame_mbs_only_flag is not set, this is field height,
> > +        * which is half the final height (see (7-18) in the
> > +        * specification)
> > +        */
> > +       if (!(h264_sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY))
> > +               height *= 2;
> > +
> > +       attributes->width = width;
> > +       attributes->height = height;
> > +       attributes->luma_bitdepth = h264_sps->bit_depth_luma_minus8 + 8;
> > +       attributes->chroma_bitdepth = h264_sps->bit_depth_chroma_minus8 + 8;
> > +       switch (h264_sps->chroma_format_idc) {
> > +       case 0:
> > +               attributes->subsampling = 400;
> > +               break;
> > +       case 1:
> > +               attributes->subsampling = 420;
> > +               break;
> > +       case 2:
> > +               attributes->subsampling = 422;
> > +               break;
> > +       case 3:
> > +               attributes->subsampling = 444;
> > +               break;
> > +       };
> > +       return 0;
> > +}
> > +
> > +static int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx, void *sps,
> > +                                   struct v4l2_pix_format_mplane *pix_mp)
> >  {
> > -       unsigned int width, height;
> > +       struct sps_attributes attributes = {0};
> > +
> > +       rkvdec_h264_get_sps_attributes(ctx, sps, &attributes);
> > 
> >         /*
> >          * TODO: The hardware supports 10-bit and 4:2:2 profiles,
> >          * but it's currently broken in the driver.
> >          * Reject them for now, until it's fixed.
> >          */
> > -       if (sps->chroma_format_idc > 1)
> > -               /* Only 4:0:0 and 4:2:0 are supported */
> > +       if (attributes.subsampling > 420) {
> > +               dev_err(ctx->dev->dev,
> > +                       "Only 4:0:0 and 4:2:0 subsampling schemes are supported, got: %d\n",
> > +                       attributes.subsampling);
> >                 return -EINVAL;
> > -       if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8)
> > -               /* Luma and chroma bit depth mismatch */
> > +       }
> > +       if (attributes.luma_bitdepth != attributes.chroma_bitdepth) {
> > +               dev_err(ctx->dev->dev,
> > +                       "Luma and chroma bit depth mismatch, luma %d, chroma %d\n",
> > +                       attributes.luma_bitdepth, attributes.chroma_bitdepth);
> >                 return -EINVAL;
> > -       if (sps->bit_depth_luma_minus8 != 0)
> > -               /* Only 8-bit is supported */
> > +       }
> > +       if (attributes.luma_bitdepth != 8) {
> > +               dev_err(ctx->dev->dev, "Only 8-bit H264 formats supported, SPS %d\n",
> > +                       attributes.luma_bitdepth);
> >                 return -EINVAL;
> > +       }
> > 
> > -       width = (sps->pic_width_in_mbs_minus1 + 1) * 16;
> > -       height = (sps->pic_height_in_map_units_minus1 + 1) * 16;
> > -
> > -       /*
> > -        * When frame_mbs_only_flag is not set, this is field height,
> > -        * which is half the final height (see (7-18) in the
> > -        * specification)
> > -        */
> > -       if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY))
> > -               height *= 2;
> > -
> > -       if (width > ctx->coded_fmt.fmt.pix_mp.width ||
> > -           height > ctx->coded_fmt.fmt.pix_mp.height)
> > +       if (attributes.width > pix_mp->width || attributes.height > pix_mp->height) {
> > +               dev_err(ctx->dev->dev,
> > +                       "Incompatible SPS dimension, SPS %dx%d, Pixel format %dx%d.",
> > +                       attributes.width, attributes.height, pix_mp->width, pix_mp->height);
> >                 return -EINVAL;
> > +       }
> > 
> >         return 0;
> >  }
> > @@ -1077,8 +1117,9 @@ static int rkvdec_h264_start(struct rkvdec_ctx *ctx)
> >         if (!ctrl)
> >                 return -EINVAL;
> > 
> > -       ret = rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps);
> > -       if (ret)
> > +       ret = rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps,
> > +                                      &ctx->coded_fmt.fmt.pix_mp);
> 
> Not a problem with this patch, but I wonder why we accepted a validation
> in the start_streaming step.

Its something we've been discussing a lot lately Benjamin / Sebastian an I (in
person, sorry for that, but sometimes we work better off chats). This is
something none of the reviewers/authors seems to have actually cared about so
far. In stateless decoders  we have FMT(OUTPUT) that contains the coded size,
S_CTRL(SOME_HEADERS) which is restricted by the size in FMT(OUTPUT)
(restrictions depends on the codec, could be ==, or smaller) but also used to
create and limit what FMT(CAPTURE) can be.

One thing that raised, is that the width/height alignment has been carelessly
applied to OUTPUT and CAPTURE, saved by the fact the real value is in SPS, but
possibly leading to strange bugs. Notably we notice that some coded sizes
rejected by S_FMT(OUTOUT) still lead to working streamon and decode :-S.

The other aspect is validation. The initial thinking was that we can validate
the SPS (SOME_HEADERS) directly when the control is set. But we found a gap,
userspace could come back and change the coded size in FMT(OUTPUT) to miss-match
the header. We can't reject that, since FMT(OUTPUT) should just always works,
its the first step according to the doc. The doc does not impose closing the
device and restarting from scratch (even though this is what our userspace
currently though). So in short, if the SPS coded size no longer match the OUTPUT
reported coded size, we needed to reject streamon, hence the validation there.
Of course, there was some more mistakes done, like trying to validate when
executing a job, but I think all of these got caught at review.

On of the reflection we have, is that to be more "semantically" aligned with
V4L2 control framework, we should instead of this ensure the the SPS is always
valid. But this is a bit of work for a usecase that no one needs. In short,
S_FMT(OUTPUT) would always reset the SPS by creating one that is valid and
maches the coded size (when the bitstream header have that, the reason its
duplicated is that we wanted to support light coding format which does not carry
that information in the bitstream). The FMT(CAPTURE) would also be reset to
something valid according to both.

Then we'd validate the SPS control against the FMT(OUTPUT) when set, and always
reset the FMT(CAPTURE) accordingly. This way, no more validation would be
required at streamon, since we ensure everything stay valid by discarding past
settings. Such a method needs careful thought, and remember a bit of work, but
it would help prevent further broken logic, for those who haven't noticed,
Hantro G2 HEVC decoder will pick NV12_4L4 by default when you pass a 10bit SPS,
cause no one noticed until today ... But that's not what the spec is expecting,
as its not a "native" format for the bitstream. What I like about this proposal
is that it would remove any remaining possible side effect from a previous
session, trully allowing for reuse of codec instance, but again, this is
theoritical, as long as you can't crash the driver (which the current validation
is about), its not a real bug, most userspace will just set everything all the
time with these CODEC.

Ok, this is getting long, but I just want to keep in mind this is multiple years
of accumulated  mistakes (or just delaying known limitation in driver designs),
we should probably not block features completely over getting this right
immediately, as all it does it makes the actual suffer longer. Though, we should
encourage cross-driver fixes whenever something is improved in one driver.

> 
> At this point, the driver accepted all the format negotiations in try_fmt.
> It's difficult for applications to recover from this, as there would
> be no way to tell what failed,
> we would be returning EINVAL, which as per the spec is "buffer type is
> not supported,
> or no buffers have been allocated (memory mapping) or enqueued (output) yet.".
> 
> I think it would really make a lot of sense to fix this now, instead of continue
> abusing it. And also, I'd like to prevent a possible anti-pattern from
> spreading.
> 
> Thanks!
> Ezequiel
> 
> > +       if (ret < 0)
> >                 return ret;
> > 
> >         h264_ctx = kzalloc(sizeof(*h264_ctx), GFP_KERNEL);
> > @@ -1175,10 +1216,21 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx)
> >         return 0;
> >  }
> > 
> > +static u32 rkvdec_h264_valid_fmt(struct rkvdec_ctx *ctx)
> > +{
> > +       /*
> > +        * Only 8 bit 4:0:0 and 4:2:0 formats supported for now.
> > +        * The SPS is validated at a different function thus we can assume that
> > +        * it is correct.
> > +        */
> > +       return V4L2_PIX_FMT_NV12;
> > +}
> > +
> >  static int rkvdec_h264_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl)
> >  {
> >         if (ctrl->id == V4L2_CID_STATELESS_H264_SPS)
> > -               return rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps);
> > +               return rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps,
> > +                                               &ctx->coded_fmt.fmt.pix_mp);
> > 
> >         return 0;
> >  }
> > @@ -1189,4 +1241,7 @@ const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops = {
> >         .stop = rkvdec_h264_stop,
> >         .run = rkvdec_h264_run,
> >         .try_ctrl = rkvdec_h264_try_ctrl,
> > +       .valid_fmt = rkvdec_h264_valid_fmt,
> > +       .sps_check = rkvdec_h264_validate_sps,
> > +       .get_sps_attributes = rkvdec_h264_get_sps_attributes,
> >  };
> > 
> > --
> > 2.25.1


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

  reply	other threads:[~2023-01-12 21:59 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-12 12:56 [PATCH v2 00/12] RkVDEC HEVC driver Sebastian Fricke
2023-01-12 12:56 ` [PATCH v2 01/12] media: v4l2: Add NV15 pixel format Sebastian Fricke
2023-01-13 12:19   ` kernel test robot
2023-02-16  8:57   ` Hsia-Jun Li
2023-02-16 17:00     ` Nicolas Dufresne
2023-02-17  2:40       ` Hsia-Jun Li
2023-01-12 12:56 ` [PATCH v2 02/12] media: v4l2-common: Add helpers to calculate bytesperline and sizeimage Sebastian Fricke
2023-01-12 12:56 ` [PATCH v2 03/12] staging: media: rkvdec: Helper for buffer queue busy check Sebastian Fricke
2023-01-16  7:54   ` Andrzej Pietrasiewicz
2023-01-12 12:56 ` [PATCH v2 04/12] staging: media: rkvdec: Block start streaming until both queues run Sebastian Fricke
2023-01-12 14:55   ` Ezequiel Garcia
2023-01-12 15:00     ` Dan Carpenter
2023-01-16  8:23   ` Andrzej Pietrasiewicz
2023-01-12 12:56 ` [PATCH v2 05/12] staging: media: rkvdec: Add SPS structure to internal context Sebastian Fricke
2023-01-12 15:02   ` Ezequiel Garcia
2023-01-16 10:00     ` Andrzej Pietrasiewicz
2023-01-12 12:56 ` [PATCH v2 06/12] staging: media: rkvdec: Add a valid pixel format check as callback Sebastian Fricke
2023-01-12 15:30   ` Ezequiel Garcia
2023-01-12 12:56 ` [PATCH v2 07/12] staging: media: rkvdec: Add a routine to fetch SPS attributes as a callback Sebastian Fricke
2023-01-16 10:27   ` Andrzej Pietrasiewicz
2023-01-12 12:56 ` [PATCH v2 08/12] staging: media: rkvdec: Add a valid SPS check " Sebastian Fricke
2023-01-12 12:56 ` [PATCH v2 09/12] staging: media: rkvdec: h264: Add callbacks for h264 Sebastian Fricke
2023-01-12 15:21   ` Ezequiel Garcia
2023-01-12 21:58     ` Nicolas Dufresne [this message]
2023-01-12 12:56 ` [PATCH v2 10/12] staging: media: rkvdec: Wrapper for pixel format preparation Sebastian Fricke
2023-01-16 10:42   ` Andrzej Pietrasiewicz
2023-01-12 12:56 ` [PATCH v2 11/12] staging: media: rkvdec: Enable S_CTRL IOCTL Sebastian Fricke
2023-01-12 15:09   ` Ezequiel Garcia
2023-01-12 22:04     ` Nicolas Dufresne
2023-01-12 12:56 ` [PATCH v2 12/12] staging: media: rkvdec: Add HEVC backend Sebastian Fricke
2023-01-12 18:27   ` kernel test robot
2023-01-16 12:44   ` Andrzej Pietrasiewicz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b0aca760a1c804d68cd95357b8adcafef0e78b25.camel@collabora.com \
    --to=nicolas.dufresne@collabora.com \
    --cc=andrzej.p@collabora.com \
    --cc=benjamin.gaignard@collabora.com \
    --cc=bob.beckett@collabora.com \
    --cc=ezequiel@vanguardiasur.com.ar \
    --cc=gregkh@linuxfoundation.org \
    --cc=jonas@kwiboo.se \
    --cc=kernel@collabora.com \
    --cc=knaerzche@gmail.com \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-rockchip@lists.infradead.org \
    --cc=linux-staging@lists.linux.dev \
    --cc=mchehab@kernel.org \
    --cc=sebastian.fricke@collabora.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox