mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-30 11:17:42 +08:00
media: v4l2-ctrls: add full AV1 profile validation in validate_av1_sequence()
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 <opensource206@gmail.com>
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
committed by
Hans Verkuil
parent
cdd0f118ef
commit
2ce45197be
@@ -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)
|
||||
{
|
||||
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;
|
||||
|
||||
/* 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))
|
||||
~(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;
|
||||
|
||||
if (s->seq_profile == 1 && s->flags & V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user