On Sat Sep 13 16:22:46 2025 +0530, Pavan Bobba wrote:
> Complete the "TODO: PROFILES" by enforcing profile-specific and
> monochrome constraints as defined by the AV1 specification
> (Section 5.5.2, "Color config syntax").
> 
> The validator now checks:
> 
>  - Flags: reject any unknown bits set in sequence->flags
>  - Profile range: only profiles 0..2 are valid
>  - Profile 0: 8/10-bit only, subsampling must be 4:2:0 (sx=1, sy=1),
>    monochrome allowed
>  - Profile 1: 8/10-bit only, subsampling must be 4:4:4 (sx=0, sy=0),
>    monochrome forbidden
>  - Profile 2:
>     * 8/10-bit: only 4:2:2 allowed (sx=1, sy=0)
>     * 12-bit: 4:4:4 (sx=0, sy=0), 4:2:2 (sx=1, sy=0), or 4:2:0 (sx=1, sy=1)
>       allowed
>  - Monochrome path (all profiles except 1): forces subsampling_x=1,
>    subsampling_y=1, separate_uv_delta_q=0
> 
> These checks prevent userspace from providing invalid AV1 sequence
> headers that would otherwise be accepted, leading to undefined driver
> or hardware behavior.
> 
> Signed-off-by: Pavan Bobba <[email protected]>
> Signed-off-by: Nicolas Dufresne <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/v4l2-core/v4l2-ctrls-core.c | 125 ++++++++++++++++++++++++------
 1 file changed, 100 insertions(+), 25 deletions(-)

---

diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c 
b/drivers/media/v4l2-core/v4l2-ctrls-core.c
index 85d07ef44f62..7c660cd61e48 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
@@ -827,39 +827,114 @@ static int validate_av1_frame(struct v4l2_ctrl_av1_frame 
*f)
        return 0;
 }
 
+/**
+ * validate_av1_sequence - validate AV1 sequence header fields
+ * @s: control struct from userspace
+ *
+ * Implements AV1 spec §5.5.2 color_config() checks that are
+ * possible with the current v4l2_ctrl_av1_sequence definition.
+ *
+ * TODO: extend validation once additional fields such as
+ *       color_primaries, transfer_characteristics,
+ *       matrix_coefficients, and chroma_sample_position
+ *       are added to the uAPI.
+ *
+ * Returns 0 if valid, -EINVAL otherwise.
+ */
 static int validate_av1_sequence(struct v4l2_ctrl_av1_sequence *s)
 {
-       if (s->flags &
-       ~(V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE |
-        V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK |
-        V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA |
-        V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER |
-        V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND |
-        V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND |
-        V4L2_AV1_SEQUENCE_FLAG_ENABLE_WARPED_MOTION |
-        V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER |
-        V4L2_AV1_SEQUENCE_FLAG_ENABLE_ORDER_HINT |
-        V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP |
-        V4L2_AV1_SEQUENCE_FLAG_ENABLE_REF_FRAME_MVS |
-        V4L2_AV1_SEQUENCE_FLAG_ENABLE_SUPERRES |
-        V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF |
-        V4L2_AV1_SEQUENCE_FLAG_ENABLE_RESTORATION |
-        V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME |
-        V4L2_AV1_SEQUENCE_FLAG_COLOR_RANGE |
-        V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_X |
-        V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_Y |
-        V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT |
-        V4L2_AV1_SEQUENCE_FLAG_SEPARATE_UV_DELTA_Q))
-               return -EINVAL;
+       const bool mono  = s->flags & V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME;
+       const bool sx    = s->flags & V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_X;
+       const bool sy    = s->flags & V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_Y;
+       const bool uv_dq = s->flags & 
V4L2_AV1_SEQUENCE_FLAG_SEPARATE_UV_DELTA_Q;
 
-       if (s->seq_profile == 1 && s->flags & 
V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME)
+       /* 1. Reject unknown flags */
+       if (s->flags &
+           ~(V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE |
+             V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK |
+             V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA |
+             V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER |
+             V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND |
+             V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND |
+             V4L2_AV1_SEQUENCE_FLAG_ENABLE_WARPED_MOTION |
+             V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER |
+             V4L2_AV1_SEQUENCE_FLAG_ENABLE_ORDER_HINT |
+             V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP |
+             V4L2_AV1_SEQUENCE_FLAG_ENABLE_REF_FRAME_MVS |
+             V4L2_AV1_SEQUENCE_FLAG_ENABLE_SUPERRES |
+             V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF |
+             V4L2_AV1_SEQUENCE_FLAG_ENABLE_RESTORATION |
+             V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME |
+             V4L2_AV1_SEQUENCE_FLAG_COLOR_RANGE |
+             V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_X |
+             V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_Y |
+             V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT |
+             V4L2_AV1_SEQUENCE_FLAG_SEPARATE_UV_DELTA_Q))
                return -EINVAL;
 
-       /* reserved */
+       /* 2. Profile range */
        if (s->seq_profile > 2)
                return -EINVAL;
 
-       /* TODO: PROFILES */
+       /* 3. Monochrome shortcut */
+       if (mono) {
+               /* Profile 1 forbids monochrome */
+               if (s->seq_profile == 1)
+                       return -EINVAL;
+
+               /* Mono → subsampling must look like 4:0:0: sx=1, sy=1 */
+               if (!sx || !sy)
+                       return -EINVAL;
+
+               /* separate_uv_delta_q must be 0 */
+               if (uv_dq)
+                       return -EINVAL;
+
+               return 0;
+       }
+
+       /* 4. Profile-specific rules */
+       switch (s->seq_profile) {
+       case 0:
+               /* Profile 0: only 8/10-bit, subsampling=4:2:0 (sx=1, sy=1) */
+               if (s->bit_depth != 8 && s->bit_depth != 10)
+                       return -EINVAL;
+               if (!(sx && sy))
+                       return -EINVAL;
+               break;
+
+       case 1:
+               /* Profile 1: only 8/10-bit, subsampling=4:4:4 (sx=0, sy=0) */
+               if (s->bit_depth != 8 && s->bit_depth != 10)
+                       return -EINVAL;
+               if (sx || sy)
+                       return -EINVAL;
+               break;
+
+       case 2:
+               /* Profile 2: 8/10/12-bit allowed */
+               if (s->bit_depth != 8 && s->bit_depth != 10 &&
+                   s->bit_depth != 12)
+                       return -EINVAL;
+
+               if (s->bit_depth == 12) {
+                       if (!sx) {
+                               /* 4:4:4 → sy must be 0 */
+                               if (sy)
+                                       return -EINVAL;
+                       } else {
+                               /* sx=1 → sy=0 (4:2:2) or sy=1 (4:2:0) */
+                               if (sy != 0 && sy != 1)
+                                       return -EINVAL;
+                       }
+               } else {
+                       /* 8/10-bit → only 4:2:2 allowed (sx=1, sy=0) */
+                       if (!(sx && !sy))
+                               return -EINVAL;
+               }
+               break;
+       }
+
        return 0;
 }
 
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to