mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 22:19:30 +02:00
Merge tag 'media/v7.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media fixes from Mauro Carvalho Chehab:
"Core:
- add bounded tile-count helpers for HEVC stateless decoders
- validate AV1 tile counts fits in array size
- validate HEVC tile counts fits in array size
- fix memcmp() size in B1 reference list comparison
mediatek:
- bound AV1 tile-start copy to fit in array size
rockchip:
- reject AV1 frames exceeding the tile size
- guard VPU981 AV1 divisor and tile buffer
hantro and rkvdec:
- bound G2 HEVC tile loops and PPS id to the buffer size
rppx1:
- read the raw pattern from the PRE2 acquisition module
- describe the MAIN_POST white balance gains block"
* tag 'media/v7.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media:
media: mediatek: vcodec: bound AV1 tile-start copy to the array capacity
media: verisilicon: rockchip: reject AV1 frames exceeding the tile capacity
media: verisilicon: rockchip: guard VPU981 AV1 divisor and tile buffer
media: verisilicon: hantro: bound G2 HEVC tile loop to the buffer capacity
media: rkvdec: bound HEVC tile loops and PPS id to the array capacity
media: hevc: add bounded tile-count helpers
media: v4l2-ctrls: validate AV1 tile counts
media: v4l2-ctrls: validate HEVC tile counts
media: v4l2-h264: Fix memcmp() size in B1 reference list comparison
media: rppx1: bls: read the raw pattern from the PRE2 acquisition module
media: rppx1: describe the MAIN_POST white balance gains block
This commit is contained in:
@@ -25,6 +25,7 @@ rppx1_ext_params_blocks_info[] = {
|
||||
RPPX1_PARAMS_BLOCK_INFO(LSC_PRE2, lsc),
|
||||
RPPX1_PARAMS_BLOCK_INFO(AWBG_PRE1, awbg),
|
||||
RPPX1_PARAMS_BLOCK_INFO(AWBG_PRE2, awbg),
|
||||
RPPX1_PARAMS_BLOCK_INFO(AWBG_POST, awbg),
|
||||
RPPX1_PARAMS_BLOCK_INFO(CCOR_POST, ccor),
|
||||
RPPX1_PARAMS_BLOCK_INFO(HIST_PRE1, hist),
|
||||
RPPX1_PARAMS_BLOCK_INFO(HIST_PRE2, hist),
|
||||
|
||||
@@ -70,7 +70,7 @@ rppx1_bls_swap_regs(struct rpp_module *mod, const u32 input[4], u32 output[4])
|
||||
|
||||
/* Swap to pattern used in our path, PRE1 or PRE2. */
|
||||
struct rpp_module *acq = mod == &mod->rpp->pre1.bls ?
|
||||
&mod->rpp->pre1.acq : &mod->rpp->pre2.bls;
|
||||
&mod->rpp->pre1.acq : &mod->rpp->pre2.acq;
|
||||
enum rpp_raw_pattern pattern = acq->info.acq.raw_pattern;
|
||||
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
|
||||
@@ -1299,11 +1299,12 @@ static void vdec_av1_slice_setup_tile(struct vdec_av1_slice_frame *frame,
|
||||
tile->uniform_tile_spacing_flag =
|
||||
BIT_FLAG(ctrl_tile, V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING);
|
||||
|
||||
for (i = 0; i < tile->tile_cols + 1; i++)
|
||||
/* Bound the copy to the mi_col_starts[]/mi_row_starts[] capacity. */
|
||||
for (i = 0; i < tile->tile_cols + 1 && i < V4L2_AV1_MAX_TILE_COLS + 1; i++)
|
||||
tile->mi_col_starts[i] =
|
||||
ALIGN(ctrl_tile->mi_col_starts[i], BIT(mib_size_log2)) >> mib_size_log2;
|
||||
|
||||
for (i = 0; i < tile->tile_rows + 1; i++)
|
||||
for (i = 0; i < tile->tile_rows + 1 && i < V4L2_AV1_MAX_TILE_ROWS + 1; i++)
|
||||
tile->mi_row_starts[i] =
|
||||
ALIGN(ctrl_tile->mi_row_starts[i], BIT(mib_size_log2)) >> mib_size_log2;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/v4l2-common.h>
|
||||
#include <media/v4l2-hevc.h>
|
||||
#include <media/v4l2-mem2mem.h>
|
||||
|
||||
#include "rkvdec.h"
|
||||
@@ -37,15 +38,17 @@ void compute_tiles_uniform(struct rkvdec_hevc_run *run, u16 log2_min_cb_size,
|
||||
s32 pic_in_cts_height, u16 *column_width, u16 *row_height)
|
||||
{
|
||||
const struct v4l2_ctrl_hevc_pps *pps = run->pps;
|
||||
unsigned int num_cols = v4l2_hevc_pps_num_tile_columns(pps);
|
||||
unsigned int num_rows = v4l2_hevc_pps_num_tile_rows(pps);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pps->num_tile_columns_minus1 + 1; i++)
|
||||
for (i = 0; i < num_cols; i++)
|
||||
column_width[i] = ((i + 1) * pic_in_cts_width) /
|
||||
(pps->num_tile_columns_minus1 + 1) -
|
||||
(i * pic_in_cts_width) /
|
||||
(pps->num_tile_columns_minus1 + 1);
|
||||
|
||||
for (i = 0; i < pps->num_tile_rows_minus1 + 1; i++)
|
||||
for (i = 0; i < num_rows; i++)
|
||||
row_height[i] = ((i + 1) * pic_in_cts_height) /
|
||||
(pps->num_tile_rows_minus1 + 1) -
|
||||
(i * pic_in_cts_height) /
|
||||
@@ -57,17 +60,20 @@ void compute_tiles_non_uniform(struct rkvdec_hevc_run *run, u16 log2_min_cb_size
|
||||
s32 pic_in_cts_height, u16 *column_width, u16 *row_height)
|
||||
{
|
||||
const struct v4l2_ctrl_hevc_pps *pps = run->pps;
|
||||
unsigned int num_cols = v4l2_hevc_pps_num_tile_columns(pps);
|
||||
unsigned int num_rows = v4l2_hevc_pps_num_tile_rows(pps);
|
||||
s32 sum = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pps->num_tile_columns_minus1; i++) {
|
||||
/* The last tile entry is written after the loop, so iterate one less. */
|
||||
for (i = 0; i < num_cols - 1; i++) {
|
||||
column_width[i] = pps->column_width_minus1[i] + 1;
|
||||
sum += column_width[i];
|
||||
}
|
||||
column_width[i] = pic_in_cts_width - sum;
|
||||
|
||||
sum = 0;
|
||||
for (i = 0; i < pps->num_tile_rows_minus1; i++) {
|
||||
for (i = 0; i < num_rows - 1; i++) {
|
||||
row_height[i] = pps->row_height_minus1[i] + 1;
|
||||
sum += row_height[i];
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
* Jeffy Chen <jeffy.chen@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <media/v4l2-hevc.h>
|
||||
#include <media/v4l2-mem2mem.h>
|
||||
|
||||
#include "rkvdec.h"
|
||||
@@ -135,6 +136,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
|
||||
* packet unit). so the driver copy SPS/PPS information to the exact PPS
|
||||
* packet unit for HW accessing.
|
||||
*/
|
||||
if (pps->pic_parameter_set_id >= ARRAY_SIZE(priv_tbl->param_set))
|
||||
return;
|
||||
hw_ps = &priv_tbl->param_set[pps->pic_parameter_set_id];
|
||||
memset(hw_ps, 0, sizeof(*hw_ps));
|
||||
|
||||
@@ -253,9 +256,9 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
|
||||
|
||||
if (pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) {
|
||||
/* Userspace also provide column width and row height for uniform spacing */
|
||||
for (i = 0; i <= pps->num_tile_columns_minus1; i++)
|
||||
for (i = 0; i < v4l2_hevc_pps_num_tile_columns(pps); i++)
|
||||
WRITE_PPS(pps->column_width_minus1[i], COLUMN_WIDTH(i));
|
||||
for (i = 0; i <= pps->num_tile_rows_minus1; i++)
|
||||
for (i = 0; i < v4l2_hevc_pps_num_tile_rows(pps); i++)
|
||||
WRITE_PPS(pps->row_height_minus1[i], ROW_HEIGHT(i));
|
||||
} else {
|
||||
WRITE_PPS(DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_y) - 1,
|
||||
|
||||
@@ -145,6 +145,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
|
||||
* packet unit). so the driver copy SPS/PPS information to the exact PPS
|
||||
* packet unit for HW accessing.
|
||||
*/
|
||||
if (pps->pic_parameter_set_id >= ARRAY_SIZE(priv_tbl->param_set))
|
||||
return;
|
||||
hw_ps = &priv_tbl->param_set[pps->pic_parameter_set_id];
|
||||
memset(hw_ps, 0, sizeof(*hw_ps));
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* Copyright (C) 2020 Safran Passenger Innovations LLC
|
||||
*/
|
||||
|
||||
#include <media/v4l2-hevc.h>
|
||||
|
||||
#include "hantro_hw.h"
|
||||
#include "hantro_g2_regs.h"
|
||||
|
||||
@@ -15,8 +17,8 @@ static void prepare_tile_info_buffer(struct hantro_ctx *ctx)
|
||||
const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
|
||||
const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
|
||||
u16 *p = (u16 *)((u8 *)ctx->hevc_dec.tile_sizes.cpu);
|
||||
unsigned int num_tile_rows = pps->num_tile_rows_minus1 + 1;
|
||||
unsigned int num_tile_cols = pps->num_tile_columns_minus1 + 1;
|
||||
unsigned int num_tile_rows = v4l2_hevc_pps_num_tile_rows(pps);
|
||||
unsigned int num_tile_cols = v4l2_hevc_pps_num_tile_columns(pps);
|
||||
unsigned int pic_width_in_ctbs, pic_height_in_ctbs;
|
||||
unsigned int max_log2_ctb_size, ctb_size;
|
||||
bool tiles_enabled, uniform_spacing;
|
||||
|
||||
@@ -431,20 +431,39 @@ static int rockchip_vpu981_av1_dec_prepare_run(struct hantro_ctx *ctx)
|
||||
{
|
||||
struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
|
||||
struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
|
||||
const struct v4l2_av1_tile_info *tile_info;
|
||||
struct v4l2_ctrl *tge;
|
||||
u32 num_tiles;
|
||||
|
||||
ctrls->sequence = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_SEQUENCE);
|
||||
if (WARN_ON(!ctrls->sequence))
|
||||
return -EINVAL;
|
||||
|
||||
ctrls->tile_group_entry =
|
||||
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY);
|
||||
if (WARN_ON(!ctrls->tile_group_entry))
|
||||
tge = v4l2_ctrl_find(&ctx->ctrl_handler,
|
||||
V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY);
|
||||
if (WARN_ON(!tge))
|
||||
return -EINVAL;
|
||||
ctrls->tile_group_entry = tge->p_cur.p;
|
||||
|
||||
ctrls->frame = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_FRAME);
|
||||
if (WARN_ON(!ctrls->frame))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* rockchip_vpu981_av1_dec_set_tile_info() indexes the tile group
|
||||
* entry array by tile1 * tile_cols + tile0, so it reads up to
|
||||
* tile_cols * tile_rows entries, and lays out one descriptor per tile
|
||||
* in the AV1_MAX_TILES tile_info buffer while programming the real
|
||||
* tile geometry into the hardware. Reject a frame that claims more
|
||||
* tiles than userspace submitted, or more than the hardware tile
|
||||
* buffer holds, so the read stays in bounds and the programmed
|
||||
* geometry matches the descriptors written.
|
||||
*/
|
||||
tile_info = &ctrls->frame->tile_info;
|
||||
num_tiles = (u32)tile_info->tile_cols * tile_info->tile_rows;
|
||||
if (num_tiles > tge->elems || num_tiles > AV1_MAX_TILES)
|
||||
return -EINVAL;
|
||||
|
||||
ctrls->film_grain =
|
||||
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_FILM_GRAIN);
|
||||
|
||||
@@ -578,16 +597,30 @@ static void rockchip_vpu981_av1_dec_set_tile_info(struct hantro_ctx *ctx)
|
||||
const struct v4l2_av1_tile_info *tile_info = &ctrls->frame->tile_info;
|
||||
const struct v4l2_ctrl_av1_tile_group_entry *group_entry =
|
||||
ctrls->tile_group_entry;
|
||||
int context_update_y =
|
||||
tile_info->context_update_tile_id / tile_info->tile_cols;
|
||||
int context_update_x =
|
||||
tile_info->context_update_tile_id % tile_info->tile_cols;
|
||||
int context_update_tile_id =
|
||||
context_update_x * tile_info->tile_rows + context_update_y;
|
||||
int context_update_y = 0;
|
||||
int context_update_x = 0;
|
||||
int context_update_tile_id = 0;
|
||||
u8 *dst = av1_dec->tile_info.cpu;
|
||||
u8 *dst_end = dst + av1_dec->tile_info.size;
|
||||
struct hantro_dev *vpu = ctx->dev;
|
||||
int tile0, tile1;
|
||||
|
||||
/*
|
||||
* tile_cols and tile_rows are bounded by the V4L2 control validation
|
||||
* (V4L2_AV1_MAX_TILE_{COLS,ROWS} and V4L2_AV1_MAX_TILE_COUNT). Guard
|
||||
* the divisor here, and keep the descriptor writes within the
|
||||
* AV1_MAX_TILES tile_info buffer below; the register values use the
|
||||
* unmodified tile geometry.
|
||||
*/
|
||||
if (tile_info->tile_cols) {
|
||||
context_update_y =
|
||||
tile_info->context_update_tile_id / tile_info->tile_cols;
|
||||
context_update_x =
|
||||
tile_info->context_update_tile_id % tile_info->tile_cols;
|
||||
context_update_tile_id =
|
||||
context_update_x * tile_info->tile_rows + context_update_y;
|
||||
}
|
||||
|
||||
memset(dst, 0, av1_dec->tile_info.size);
|
||||
|
||||
for (tile0 = 0; tile0 < tile_info->tile_cols; tile0++) {
|
||||
@@ -598,6 +631,10 @@ static void rockchip_vpu981_av1_dec_set_tile_info(struct hantro_ctx *ctx)
|
||||
tile_info->height_in_sbs_minus_1[tile1] + 1;
|
||||
u32 x0 = tile_info->width_in_sbs_minus_1[tile0] + 1;
|
||||
|
||||
/* Stop once the tile_info descriptor buffer is full. */
|
||||
if (dst + 16 > dst_end)
|
||||
break;
|
||||
|
||||
/* tile size in SB units (width,height) */
|
||||
*dst++ = x0;
|
||||
*dst++ = 0;
|
||||
@@ -622,6 +659,8 @@ static void rockchip_vpu981_av1_dec_set_tile_info(struct hantro_ctx *ctx)
|
||||
*dst++ = (end >> 16) & 255;
|
||||
*dst++ = (end >> 24) & 255;
|
||||
}
|
||||
if (dst + 16 > dst_end)
|
||||
break;
|
||||
}
|
||||
|
||||
hantro_reg_write(vpu, &av1_multicore_expect_context_update, !!(context_update_x == 0));
|
||||
|
||||
@@ -793,10 +793,30 @@ static int validate_av1_film_grain(struct v4l2_ctrl_av1_film_grain *fg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int validate_av1_tile_info(struct v4l2_av1_tile_info *t)
|
||||
{
|
||||
/*
|
||||
* tile_cols and tile_rows index the per-tile descriptor arrays and
|
||||
* bound the tile loops in the stateless AV1 drivers; the product
|
||||
* bounds the total tile descriptor count.
|
||||
*/
|
||||
if (t->tile_cols > V4L2_AV1_MAX_TILE_COLS ||
|
||||
t->tile_rows > V4L2_AV1_MAX_TILE_ROWS)
|
||||
return -EINVAL;
|
||||
|
||||
if ((u32)t->tile_cols * t->tile_rows > V4L2_AV1_MAX_TILE_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int validate_av1_frame(struct v4l2_ctrl_av1_frame *f)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = validate_av1_tile_info(&f->tile_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = validate_av1_quantization(&f->quantization);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1253,6 +1273,18 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
||||
|
||||
p_hevc_pps->flags &=
|
||||
~V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED;
|
||||
} else {
|
||||
/*
|
||||
* These count the entries the stateless HEVC drivers
|
||||
* read from column_width_minus1[] / row_height_minus1[]
|
||||
* and use as tile-loop bounds.
|
||||
*/
|
||||
if (p_hevc_pps->num_tile_columns_minus1 >=
|
||||
ARRAY_SIZE(p_hevc_pps->column_width_minus1))
|
||||
return -EINVAL;
|
||||
if (p_hevc_pps->num_tile_rows_minus1 >=
|
||||
ARRAY_SIZE(p_hevc_pps->row_height_minus1))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (p_hevc_pps->flags &
|
||||
|
||||
@@ -440,7 +440,8 @@ v4l2_h264_build_b_ref_lists(const struct v4l2_h264_reflist_builder *builder,
|
||||
}
|
||||
|
||||
if (builder->num_valid > 1 &&
|
||||
!memcmp(b1_reflist, b0_reflist, builder->num_valid))
|
||||
!memcmp(b1_reflist, b0_reflist,
|
||||
sizeof(b1_reflist[0]) * builder->num_valid))
|
||||
swap(b1_reflist[0], b1_reflist[1]);
|
||||
|
||||
print_ref_list_b(builder, b0_reflist, 0);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Helper functions for HEVC stateless codecs.
|
||||
*/
|
||||
|
||||
#ifndef _MEDIA_V4L2_HEVC_H
|
||||
#define _MEDIA_V4L2_HEVC_H
|
||||
|
||||
#include <linux/minmax.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
|
||||
/**
|
||||
* v4l2_hevc_pps_num_tile_columns - number of HEVC tile columns, bounded
|
||||
* @pps: the V4L2 HEVC PPS control
|
||||
*
|
||||
* Return the number of tile columns (num_tile_columns_minus1 + 1) clamped to
|
||||
* the capacity of column_width_minus1[]. The control validation already
|
||||
* rejects out-of-range counts; this keeps the consuming drivers bounded too.
|
||||
*/
|
||||
static inline unsigned int
|
||||
v4l2_hevc_pps_num_tile_columns(const struct v4l2_ctrl_hevc_pps *pps)
|
||||
{
|
||||
return min_t(unsigned int, pps->num_tile_columns_minus1 + 1,
|
||||
ARRAY_SIZE(pps->column_width_minus1));
|
||||
}
|
||||
|
||||
/**
|
||||
* v4l2_hevc_pps_num_tile_rows - number of HEVC tile rows, bounded
|
||||
* @pps: the V4L2 HEVC PPS control
|
||||
*
|
||||
* Return the number of tile rows (num_tile_rows_minus1 + 1) clamped to the
|
||||
* capacity of row_height_minus1[].
|
||||
*/
|
||||
static inline unsigned int
|
||||
v4l2_hevc_pps_num_tile_rows(const struct v4l2_ctrl_hevc_pps *pps)
|
||||
{
|
||||
return min_t(unsigned int, pps->num_tile_rows_minus1 + 1,
|
||||
ARRAY_SIZE(pps->row_height_minus1));
|
||||
}
|
||||
|
||||
#endif /* _MEDIA_V4L2_HEVC_H */
|
||||
Reference in New Issue
Block a user