mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 15:41:52 +02:00
media: rkvdec: Move h264 functions to common file
This is a preparation commit to add support for new variants of the decoder. The functions will later be shared with vdpu381 (rk3588) and vdpu383 (rk3576). Tested-by: Diederik de Haas <didi.debian@cknow.org> # Rock 5B Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com> Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
parent
cf29115a68
commit
560438ed7c
|
|
@ -4,5 +4,6 @@ rockchip-vdec-y += \
|
|||
rkvdec.o \
|
||||
rkvdec-cabac.o \
|
||||
rkvdec-h264.o \
|
||||
rkvdec-h264-common.o \
|
||||
rkvdec-hevc.o \
|
||||
rkvdec-vp9.o
|
||||
|
|
|
|||
258
drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.c
Normal file
258
drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.c
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Rockchip video decoder h264 common functions
|
||||
*
|
||||
* Copyright (C) 2025 Collabora, Ltd.
|
||||
* Detlev Casanova <detlev.casanova@collabora.com>
|
||||
*
|
||||
* Copyright (C) 2019 Collabora, Ltd.
|
||||
* Boris Brezillon <boris.brezillon@collabora.com>
|
||||
*
|
||||
* Copyright (C) 2016 Rockchip Electronics Co., Ltd.
|
||||
* Jeffy Chen <jeffy.chen@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <linux/v4l2-common.h>
|
||||
#include <media/v4l2-h264.h>
|
||||
#include <media/v4l2-mem2mem.h>
|
||||
|
||||
#include "rkvdec.h"
|
||||
#include "rkvdec-h264-common.h"
|
||||
|
||||
#define RKVDEC_NUM_REFLIST 3
|
||||
|
||||
static void set_dpb_info(struct rkvdec_rps_entry *entries,
|
||||
u8 reflist,
|
||||
u8 refnum,
|
||||
u8 info,
|
||||
bool bottom)
|
||||
{
|
||||
struct rkvdec_rps_entry *entry = &entries[(reflist * 4) + refnum / 8];
|
||||
u8 idx = refnum % 8;
|
||||
|
||||
switch (idx) {
|
||||
case 0:
|
||||
entry->dpb_info0 = info;
|
||||
entry->bottom_flag0 = bottom;
|
||||
break;
|
||||
case 1:
|
||||
entry->dpb_info1 = info;
|
||||
entry->bottom_flag1 = bottom;
|
||||
break;
|
||||
case 2:
|
||||
entry->dpb_info2 = info;
|
||||
entry->bottom_flag2 = bottom;
|
||||
break;
|
||||
case 3:
|
||||
entry->dpb_info3 = info;
|
||||
entry->bottom_flag3 = bottom;
|
||||
break;
|
||||
case 4:
|
||||
entry->dpb_info4 = info;
|
||||
entry->bottom_flag4 = bottom;
|
||||
break;
|
||||
case 5:
|
||||
entry->dpb_info5 = info;
|
||||
entry->bottom_flag5 = bottom;
|
||||
break;
|
||||
case 6:
|
||||
entry->dpb_info6 = info;
|
||||
entry->bottom_flag6 = bottom;
|
||||
break;
|
||||
case 7:
|
||||
entry->dpb_info7 = info;
|
||||
entry->bottom_flag7 = bottom;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void lookup_ref_buf_idx(struct rkvdec_ctx *ctx,
|
||||
struct rkvdec_h264_run *run)
|
||||
{
|
||||
const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) {
|
||||
struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
|
||||
const struct v4l2_h264_dpb_entry *dpb = run->decode_params->dpb;
|
||||
struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
|
||||
struct vb2_buffer *buf = NULL;
|
||||
|
||||
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) {
|
||||
buf = vb2_find_buffer(cap_q, dpb[i].reference_ts);
|
||||
if (!buf)
|
||||
pr_debug("No buffer for reference_ts %llu",
|
||||
dpb[i].reference_ts);
|
||||
}
|
||||
|
||||
run->ref_buf[i] = buf;
|
||||
}
|
||||
}
|
||||
|
||||
void assemble_hw_rps(struct v4l2_h264_reflist_builder *builder,
|
||||
struct rkvdec_h264_run *run,
|
||||
struct rkvdec_h264_reflists *reflists,
|
||||
struct rkvdec_rps *hw_rps)
|
||||
{
|
||||
const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params;
|
||||
const struct v4l2_h264_dpb_entry *dpb = dec_params->dpb;
|
||||
|
||||
u32 i, j;
|
||||
|
||||
memset(hw_rps, 0, sizeof(*hw_rps));
|
||||
|
||||
/*
|
||||
* Assign an invalid pic_num if DPB entry at that position is inactive.
|
||||
* If we assign 0 in that position hardware will treat that as a real
|
||||
* reference picture with pic_num 0, triggering output picture
|
||||
* corruption.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) {
|
||||
if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
|
||||
continue;
|
||||
|
||||
hw_rps->frame_num[i] = builder->refs[i].frame_num;
|
||||
}
|
||||
|
||||
for (j = 0; j < RKVDEC_NUM_REFLIST; j++) {
|
||||
for (i = 0; i < builder->num_valid; i++) {
|
||||
struct v4l2_h264_reference *ref;
|
||||
bool dpb_valid;
|
||||
bool bottom;
|
||||
|
||||
switch (j) {
|
||||
case 0:
|
||||
ref = &reflists->p[i];
|
||||
break;
|
||||
case 1:
|
||||
ref = &reflists->b0[i];
|
||||
break;
|
||||
case 2:
|
||||
ref = &reflists->b1[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (WARN_ON(ref->index >= ARRAY_SIZE(dec_params->dpb)))
|
||||
continue;
|
||||
|
||||
dpb_valid = !!(run->ref_buf[ref->index]);
|
||||
bottom = ref->fields == V4L2_H264_BOTTOM_FIELD_REF;
|
||||
|
||||
set_dpb_info(hw_rps->entries, j, i, ref->index | (dpb_valid << 4), bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assemble_hw_scaling_list(struct rkvdec_h264_run *run,
|
||||
struct rkvdec_h264_scaling_list *scaling_list)
|
||||
{
|
||||
const struct v4l2_ctrl_h264_scaling_matrix *scaling = run->scaling_matrix;
|
||||
const struct v4l2_ctrl_h264_pps *pps = run->pps;
|
||||
|
||||
if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
|
||||
return;
|
||||
|
||||
BUILD_BUG_ON(sizeof(scaling_list->scaling_list_4x4) !=
|
||||
sizeof(scaling->scaling_list_4x4));
|
||||
BUILD_BUG_ON(sizeof(scaling_list->scaling_list_8x8) !=
|
||||
sizeof(scaling->scaling_list_8x8));
|
||||
|
||||
memcpy(scaling_list->scaling_list_4x4,
|
||||
scaling->scaling_list_4x4,
|
||||
sizeof(scaling->scaling_list_4x4));
|
||||
|
||||
memcpy(scaling_list->scaling_list_8x8,
|
||||
scaling->scaling_list_8x8,
|
||||
sizeof(scaling->scaling_list_8x8));
|
||||
}
|
||||
|
||||
#define RKVDEC_H264_MAX_DEPTH_IN_BYTES 2
|
||||
|
||||
int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp;
|
||||
|
||||
fmt->num_planes = 1;
|
||||
if (!fmt->plane_fmt[0].sizeimage)
|
||||
fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height *
|
||||
RKVDEC_H264_MAX_DEPTH_IN_BYTES;
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum rkvdec_image_fmt rkvdec_h264_get_image_fmt(struct rkvdec_ctx *ctx,
|
||||
struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps;
|
||||
|
||||
if (ctrl->id != V4L2_CID_STATELESS_H264_SPS)
|
||||
return RKVDEC_IMG_FMT_ANY;
|
||||
|
||||
if (sps->bit_depth_luma_minus8 == 0) {
|
||||
if (sps->chroma_format_idc == 2)
|
||||
return RKVDEC_IMG_FMT_422_8BIT;
|
||||
else
|
||||
return RKVDEC_IMG_FMT_420_8BIT;
|
||||
} else if (sps->bit_depth_luma_minus8 == 2) {
|
||||
if (sps->chroma_format_idc == 2)
|
||||
return RKVDEC_IMG_FMT_422_10BIT;
|
||||
else
|
||||
return RKVDEC_IMG_FMT_420_10BIT;
|
||||
}
|
||||
|
||||
return RKVDEC_IMG_FMT_ANY;
|
||||
}
|
||||
|
||||
int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx,
|
||||
const struct v4l2_ctrl_h264_sps *sps)
|
||||
{
|
||||
unsigned int width, height;
|
||||
|
||||
if (sps->chroma_format_idc > 2)
|
||||
/* Only 4:0:0, 4:2:0 and 4:2:2 are supported */
|
||||
return -EINVAL;
|
||||
if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8)
|
||||
/* Luma and chroma bit depth mismatch */
|
||||
return -EINVAL;
|
||||
if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2)
|
||||
/* Only 8-bit and 10-bit is supported */
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rkvdec_h264_run_preamble(struct rkvdec_ctx *ctx,
|
||||
struct rkvdec_h264_run *run)
|
||||
{
|
||||
struct v4l2_ctrl *ctrl;
|
||||
|
||||
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
||||
V4L2_CID_STATELESS_H264_DECODE_PARAMS);
|
||||
run->decode_params = ctrl ? ctrl->p_cur.p : NULL;
|
||||
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
||||
V4L2_CID_STATELESS_H264_SPS);
|
||||
run->sps = ctrl ? ctrl->p_cur.p : NULL;
|
||||
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
||||
V4L2_CID_STATELESS_H264_PPS);
|
||||
run->pps = ctrl ? ctrl->p_cur.p : NULL;
|
||||
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
||||
V4L2_CID_STATELESS_H264_SCALING_MATRIX);
|
||||
run->scaling_matrix = ctrl ? ctrl->p_cur.p : NULL;
|
||||
|
||||
rkvdec_run_preamble(ctx, &run->base);
|
||||
}
|
||||
85
drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.h
Normal file
85
drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Rockchip video decoder h264 common functions
|
||||
*
|
||||
* Copyright (C) 2025 Collabora, Ltd.
|
||||
* Detlev Casanova <detlev.casanova@collabora.com>
|
||||
*
|
||||
* Copyright (C) 2019 Collabora, Ltd.
|
||||
* Boris Brezillon <boris.brezillon@collabora.com>
|
||||
*
|
||||
* Copyright (C) 2016 Rockchip Electronics Co., Ltd.
|
||||
* Jeffy Chen <jeffy.chen@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <media/v4l2-h264.h>
|
||||
#include <media/v4l2-mem2mem.h>
|
||||
|
||||
#include "rkvdec.h"
|
||||
|
||||
struct rkvdec_h264_scaling_list {
|
||||
u8 scaling_list_4x4[6][16];
|
||||
u8 scaling_list_8x8[6][64];
|
||||
u8 padding[128];
|
||||
};
|
||||
|
||||
struct rkvdec_h264_reflists {
|
||||
struct v4l2_h264_reference p[V4L2_H264_REF_LIST_LEN];
|
||||
struct v4l2_h264_reference b0[V4L2_H264_REF_LIST_LEN];
|
||||
struct v4l2_h264_reference b1[V4L2_H264_REF_LIST_LEN];
|
||||
};
|
||||
|
||||
struct rkvdec_h264_run {
|
||||
struct rkvdec_run base;
|
||||
const struct v4l2_ctrl_h264_decode_params *decode_params;
|
||||
const struct v4l2_ctrl_h264_sps *sps;
|
||||
const struct v4l2_ctrl_h264_pps *pps;
|
||||
const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix;
|
||||
struct vb2_buffer *ref_buf[V4L2_H264_NUM_DPB_ENTRIES];
|
||||
};
|
||||
|
||||
struct rkvdec_rps_entry {
|
||||
u32 dpb_info0: 5;
|
||||
u32 bottom_flag0: 1;
|
||||
u32 view_index_off0: 1;
|
||||
u32 dpb_info1: 5;
|
||||
u32 bottom_flag1: 1;
|
||||
u32 view_index_off1: 1;
|
||||
u32 dpb_info2: 5;
|
||||
u32 bottom_flag2: 1;
|
||||
u32 view_index_off2: 1;
|
||||
u32 dpb_info3: 5;
|
||||
u32 bottom_flag3: 1;
|
||||
u32 view_index_off3: 1;
|
||||
u32 dpb_info4: 5;
|
||||
u32 bottom_flag4: 1;
|
||||
u32 view_index_off4: 1;
|
||||
u32 dpb_info5: 5;
|
||||
u32 bottom_flag5: 1;
|
||||
u32 view_index_off5: 1;
|
||||
u32 dpb_info6: 5;
|
||||
u32 bottom_flag6: 1;
|
||||
u32 view_index_off6: 1;
|
||||
u32 dpb_info7: 5;
|
||||
u32 bottom_flag7: 1;
|
||||
u32 view_index_off7: 1;
|
||||
} __packed;
|
||||
|
||||
struct rkvdec_rps {
|
||||
u16 frame_num[16];
|
||||
u32 reserved0;
|
||||
struct rkvdec_rps_entry entries[12];
|
||||
u32 reserved1[66];
|
||||
} __packed;
|
||||
|
||||
void lookup_ref_buf_idx(struct rkvdec_ctx *ctx, struct rkvdec_h264_run *run);
|
||||
void assemble_hw_rps(struct v4l2_h264_reflist_builder *builder,
|
||||
struct rkvdec_h264_run *run,
|
||||
struct rkvdec_h264_reflists *reflists,
|
||||
struct rkvdec_rps *hw_rps);
|
||||
void assemble_hw_scaling_list(struct rkvdec_h264_run *run,
|
||||
struct rkvdec_h264_scaling_list *scaling_list);
|
||||
int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f);
|
||||
enum rkvdec_image_fmt rkvdec_h264_get_image_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl);
|
||||
int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx, const struct v4l2_ctrl_h264_sps *sps);
|
||||
void rkvdec_h264_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_h264_run *run);
|
||||
|
|
@ -15,57 +15,16 @@
|
|||
#include "rkvdec.h"
|
||||
#include "rkvdec-regs.h"
|
||||
#include "rkvdec-cabac.h"
|
||||
#include "rkvdec-h264-common.h"
|
||||
|
||||
/* Size with u32 units. */
|
||||
#define RKV_CABAC_INIT_BUFFER_SIZE (3680 + 128)
|
||||
#define RKV_ERROR_INFO_SIZE (256 * 144 * 4)
|
||||
|
||||
#define RKVDEC_NUM_REFLIST 3
|
||||
|
||||
struct rkvdec_h264_scaling_list {
|
||||
u8 scaling_list_4x4[6][16];
|
||||
u8 scaling_list_8x8[6][64];
|
||||
u8 padding[128];
|
||||
};
|
||||
|
||||
struct rkvdec_sps_pps_packet {
|
||||
u32 info[8];
|
||||
};
|
||||
|
||||
struct rkvdec_rps_entry {
|
||||
u32 dpb_info0: 5;
|
||||
u32 bottom_flag0: 1;
|
||||
u32 view_index_off0: 1;
|
||||
u32 dpb_info1: 5;
|
||||
u32 bottom_flag1: 1;
|
||||
u32 view_index_off1: 1;
|
||||
u32 dpb_info2: 5;
|
||||
u32 bottom_flag2: 1;
|
||||
u32 view_index_off2: 1;
|
||||
u32 dpb_info3: 5;
|
||||
u32 bottom_flag3: 1;
|
||||
u32 view_index_off3: 1;
|
||||
u32 dpb_info4: 5;
|
||||
u32 bottom_flag4: 1;
|
||||
u32 view_index_off4: 1;
|
||||
u32 dpb_info5: 5;
|
||||
u32 bottom_flag5: 1;
|
||||
u32 view_index_off5: 1;
|
||||
u32 dpb_info6: 5;
|
||||
u32 bottom_flag6: 1;
|
||||
u32 view_index_off6: 1;
|
||||
u32 dpb_info7: 5;
|
||||
u32 bottom_flag7: 1;
|
||||
u32 view_index_off7: 1;
|
||||
} __packed;
|
||||
|
||||
struct rkvdec_rps {
|
||||
u16 frame_num[16];
|
||||
u32 reserved0;
|
||||
struct rkvdec_rps_entry entries[12];
|
||||
u32 reserved1[66];
|
||||
} __packed;
|
||||
|
||||
struct rkvdec_ps_field {
|
||||
u16 offset;
|
||||
u8 len;
|
||||
|
|
@ -117,11 +76,6 @@ struct rkvdec_ps_field {
|
|||
#define SCALING_LIST_ADDRESS PS_FIELD(184, 32)
|
||||
#define IS_LONG_TERM(i) PS_FIELD(216 + (i), 1)
|
||||
|
||||
#define DPB_OFFS(i, j) (288 + ((j) * 32 * 7) + ((i) * 7))
|
||||
#define DPB_INFO(i, j) PS_FIELD(DPB_OFFS(i, j), 5)
|
||||
#define BOTTOM_FLAG(i, j) PS_FIELD(DPB_OFFS(i, j) + 5, 1)
|
||||
#define VIEW_INDEX_OFF(i, j) PS_FIELD(DPB_OFFS(i, j) + 6, 1)
|
||||
|
||||
/* Data structure describing auxiliary buffer format. */
|
||||
struct rkvdec_h264_priv_tbl {
|
||||
s8 cabac_table[4][464][2];
|
||||
|
|
@ -131,21 +85,6 @@ struct rkvdec_h264_priv_tbl {
|
|||
u8 err_info[RKV_ERROR_INFO_SIZE];
|
||||
};
|
||||
|
||||
struct rkvdec_h264_reflists {
|
||||
struct v4l2_h264_reference p[V4L2_H264_REF_LIST_LEN];
|
||||
struct v4l2_h264_reference b0[V4L2_H264_REF_LIST_LEN];
|
||||
struct v4l2_h264_reference b1[V4L2_H264_REF_LIST_LEN];
|
||||
};
|
||||
|
||||
struct rkvdec_h264_run {
|
||||
struct rkvdec_run base;
|
||||
const struct v4l2_ctrl_h264_decode_params *decode_params;
|
||||
const struct v4l2_ctrl_h264_sps *sps;
|
||||
const struct v4l2_ctrl_h264_pps *pps;
|
||||
const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix;
|
||||
struct vb2_buffer *ref_buf[V4L2_H264_NUM_DPB_ENTRIES];
|
||||
};
|
||||
|
||||
struct rkvdec_h264_ctx {
|
||||
struct rkvdec_aux_buf priv_tbl;
|
||||
struct rkvdec_h264_reflists reflists;
|
||||
|
|
@ -269,155 +208,6 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
static void lookup_ref_buf_idx(struct rkvdec_ctx *ctx,
|
||||
struct rkvdec_h264_run *run)
|
||||
{
|
||||
const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) {
|
||||
struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
|
||||
const struct v4l2_h264_dpb_entry *dpb = run->decode_params->dpb;
|
||||
struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
|
||||
struct vb2_buffer *buf = NULL;
|
||||
|
||||
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) {
|
||||
buf = vb2_find_buffer(cap_q, dpb[i].reference_ts);
|
||||
if (!buf)
|
||||
pr_debug("No buffer for reference_ts %llu",
|
||||
dpb[i].reference_ts);
|
||||
}
|
||||
|
||||
run->ref_buf[i] = buf;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_dpb_info(struct rkvdec_rps_entry *entries,
|
||||
u8 reflist,
|
||||
u8 refnum,
|
||||
u8 info,
|
||||
bool bottom)
|
||||
{
|
||||
struct rkvdec_rps_entry *entry = &entries[(reflist * 4) + refnum / 8];
|
||||
u8 idx = refnum % 8;
|
||||
|
||||
switch (idx) {
|
||||
case 0:
|
||||
entry->dpb_info0 = info;
|
||||
entry->bottom_flag0 = bottom;
|
||||
break;
|
||||
case 1:
|
||||
entry->dpb_info1 = info;
|
||||
entry->bottom_flag1 = bottom;
|
||||
break;
|
||||
case 2:
|
||||
entry->dpb_info2 = info;
|
||||
entry->bottom_flag2 = bottom;
|
||||
break;
|
||||
case 3:
|
||||
entry->dpb_info3 = info;
|
||||
entry->bottom_flag3 = bottom;
|
||||
break;
|
||||
case 4:
|
||||
entry->dpb_info4 = info;
|
||||
entry->bottom_flag4 = bottom;
|
||||
break;
|
||||
case 5:
|
||||
entry->dpb_info5 = info;
|
||||
entry->bottom_flag5 = bottom;
|
||||
break;
|
||||
case 6:
|
||||
entry->dpb_info6 = info;
|
||||
entry->bottom_flag6 = bottom;
|
||||
break;
|
||||
case 7:
|
||||
entry->dpb_info7 = info;
|
||||
entry->bottom_flag7 = bottom;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void assemble_hw_rps(struct rkvdec_ctx *ctx,
|
||||
struct v4l2_h264_reflist_builder *builder,
|
||||
struct rkvdec_h264_run *run)
|
||||
{
|
||||
const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params;
|
||||
const struct v4l2_h264_dpb_entry *dpb = dec_params->dpb;
|
||||
struct rkvdec_h264_ctx *h264_ctx = ctx->priv;
|
||||
struct rkvdec_h264_priv_tbl *priv_tbl = h264_ctx->priv_tbl.cpu;
|
||||
|
||||
struct rkvdec_rps *hw_rps = &priv_tbl->rps;
|
||||
u32 i, j;
|
||||
|
||||
memset(hw_rps, 0, sizeof(*hw_rps));
|
||||
|
||||
/*
|
||||
* Assign an invalid pic_num if DPB entry at that position is inactive.
|
||||
* If we assign 0 in that position hardware will treat that as a real
|
||||
* reference picture with pic_num 0, triggering output picture
|
||||
* corruption.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) {
|
||||
if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
|
||||
continue;
|
||||
|
||||
hw_rps->frame_num[i] = builder->refs[i].frame_num;
|
||||
}
|
||||
|
||||
for (j = 0; j < RKVDEC_NUM_REFLIST; j++) {
|
||||
for (i = 0; i < builder->num_valid; i++) {
|
||||
struct v4l2_h264_reference *ref;
|
||||
bool dpb_valid;
|
||||
bool bottom;
|
||||
|
||||
switch (j) {
|
||||
case 0:
|
||||
ref = &h264_ctx->reflists.p[i];
|
||||
break;
|
||||
case 1:
|
||||
ref = &h264_ctx->reflists.b0[i];
|
||||
break;
|
||||
case 2:
|
||||
ref = &h264_ctx->reflists.b1[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (WARN_ON(ref->index >= ARRAY_SIZE(dec_params->dpb)))
|
||||
continue;
|
||||
|
||||
dpb_valid = run->ref_buf[ref->index] != NULL;
|
||||
bottom = ref->fields == V4L2_H264_BOTTOM_FIELD_REF;
|
||||
|
||||
set_dpb_info(hw_rps->entries, j, i, ref->index | (dpb_valid << 4), bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void assemble_hw_scaling_list(struct rkvdec_ctx *ctx,
|
||||
struct rkvdec_h264_run *run)
|
||||
{
|
||||
const struct v4l2_ctrl_h264_scaling_matrix *scaling = run->scaling_matrix;
|
||||
const struct v4l2_ctrl_h264_pps *pps = run->pps;
|
||||
struct rkvdec_h264_ctx *h264_ctx = ctx->priv;
|
||||
struct rkvdec_h264_priv_tbl *tbl = h264_ctx->priv_tbl.cpu;
|
||||
|
||||
if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
|
||||
return;
|
||||
|
||||
BUILD_BUG_ON(sizeof(tbl->scaling_list.scaling_list_4x4) !=
|
||||
sizeof(scaling->scaling_list_4x4));
|
||||
BUILD_BUG_ON(sizeof(tbl->scaling_list.scaling_list_8x8) !=
|
||||
sizeof(scaling->scaling_list_8x8));
|
||||
|
||||
memcpy(tbl->scaling_list.scaling_list_4x4,
|
||||
scaling->scaling_list_4x4,
|
||||
sizeof(scaling->scaling_list_4x4));
|
||||
|
||||
memcpy(tbl->scaling_list.scaling_list_8x8,
|
||||
scaling->scaling_list_8x8,
|
||||
sizeof(scaling->scaling_list_8x8));
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the ref POC in the correct register.
|
||||
*
|
||||
|
|
@ -568,76 +358,6 @@ static void config_registers(struct rkvdec_ctx *ctx,
|
|||
MIN(sizeof(*regs), sizeof(u32) * rkvdec->variant->num_regs));
|
||||
}
|
||||
|
||||
#define RKVDEC_H264_MAX_DEPTH_IN_BYTES 2
|
||||
|
||||
static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp;
|
||||
|
||||
fmt->num_planes = 1;
|
||||
if (!fmt->plane_fmt[0].sizeimage)
|
||||
fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height *
|
||||
RKVDEC_H264_MAX_DEPTH_IN_BYTES;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum rkvdec_image_fmt rkvdec_h264_get_image_fmt(struct rkvdec_ctx *ctx,
|
||||
struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps;
|
||||
|
||||
if (ctrl->id != V4L2_CID_STATELESS_H264_SPS)
|
||||
return RKVDEC_IMG_FMT_ANY;
|
||||
|
||||
if (sps->bit_depth_luma_minus8 == 0) {
|
||||
if (sps->chroma_format_idc == 2)
|
||||
return RKVDEC_IMG_FMT_422_8BIT;
|
||||
else
|
||||
return RKVDEC_IMG_FMT_420_8BIT;
|
||||
} else if (sps->bit_depth_luma_minus8 == 2) {
|
||||
if (sps->chroma_format_idc == 2)
|
||||
return RKVDEC_IMG_FMT_422_10BIT;
|
||||
else
|
||||
return RKVDEC_IMG_FMT_420_10BIT;
|
||||
}
|
||||
|
||||
return RKVDEC_IMG_FMT_ANY;
|
||||
}
|
||||
|
||||
static int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx,
|
||||
const struct v4l2_ctrl_h264_sps *sps)
|
||||
{
|
||||
unsigned int width, height;
|
||||
|
||||
if (sps->chroma_format_idc > 2)
|
||||
/* Only 4:0:0, 4:2:0 and 4:2:2 are supported */
|
||||
return -EINVAL;
|
||||
if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8)
|
||||
/* Luma and chroma bit depth mismatch */
|
||||
return -EINVAL;
|
||||
if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2)
|
||||
/* Only 8-bit and 10-bit is supported */
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rkvdec_h264_start(struct rkvdec_ctx *ctx)
|
||||
{
|
||||
struct rkvdec_dev *rkvdec = ctx->dev;
|
||||
|
|
@ -689,33 +409,13 @@ static void rkvdec_h264_stop(struct rkvdec_ctx *ctx)
|
|||
kfree(h264_ctx);
|
||||
}
|
||||
|
||||
static void rkvdec_h264_run_preamble(struct rkvdec_ctx *ctx,
|
||||
struct rkvdec_h264_run *run)
|
||||
{
|
||||
struct v4l2_ctrl *ctrl;
|
||||
|
||||
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
||||
V4L2_CID_STATELESS_H264_DECODE_PARAMS);
|
||||
run->decode_params = ctrl ? ctrl->p_cur.p : NULL;
|
||||
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
||||
V4L2_CID_STATELESS_H264_SPS);
|
||||
run->sps = ctrl ? ctrl->p_cur.p : NULL;
|
||||
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
||||
V4L2_CID_STATELESS_H264_PPS);
|
||||
run->pps = ctrl ? ctrl->p_cur.p : NULL;
|
||||
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
|
||||
V4L2_CID_STATELESS_H264_SCALING_MATRIX);
|
||||
run->scaling_matrix = ctrl ? ctrl->p_cur.p : NULL;
|
||||
|
||||
rkvdec_run_preamble(ctx, &run->base);
|
||||
}
|
||||
|
||||
static int rkvdec_h264_run(struct rkvdec_ctx *ctx)
|
||||
{
|
||||
struct v4l2_h264_reflist_builder reflist_builder;
|
||||
struct rkvdec_dev *rkvdec = ctx->dev;
|
||||
struct rkvdec_h264_ctx *h264_ctx = ctx->priv;
|
||||
struct rkvdec_h264_run run;
|
||||
struct rkvdec_h264_priv_tbl *tbl = h264_ctx->priv_tbl.cpu;
|
||||
|
||||
rkvdec_h264_run_preamble(ctx, &run);
|
||||
|
||||
|
|
@ -726,10 +426,10 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx)
|
|||
v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0,
|
||||
h264_ctx->reflists.b1);
|
||||
|
||||
assemble_hw_scaling_list(ctx, &run);
|
||||
assemble_hw_scaling_list(&run, &tbl->scaling_list);
|
||||
assemble_hw_pps(ctx, &run);
|
||||
lookup_ref_buf_idx(ctx, &run);
|
||||
assemble_hw_rps(ctx, &reflist_builder, &run);
|
||||
assemble_hw_rps(&reflist_builder, &run, &h264_ctx->reflists, &tbl->rps);
|
||||
config_registers(ctx, &run);
|
||||
|
||||
rkvdec_run_postamble(ctx, &run.base);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user