fixup! lavf/rkrga: add RKRGA scale, vpp and overlay filter

refine colorspace conversion handling.

Signed-off-by: nyanmisaka <nst799610810@gmail.com>
This commit is contained in:
nyanmisaka
2025-06-01 23:47:26 +08:00
parent 5ab1a0b7ba
commit 7d7212cb3f

View File

@@ -258,78 +258,90 @@ static RGAFrame *get_free_frame(RGAFrame **list)
return out; return out;
} }
static void set_colorspace_info(RGAFrameInfo *in_info, const AVFrame *in, static void set_colorspace_info(RGAFrameInfo *in_info,
RGAFrameInfo *out_info, AVFrame *out, enum AVColorSpace in_spc,
int *color_space_mode) enum AVColorRange in_rng,
RGAFrameInfo *out_info,
enum AVColorSpace *out_spc,
enum AVColorRange *out_rng,
int *color_space_mode,
int is_rga2_used)
{ {
if (!in_info || !out_info || !in || !out || !color_space_mode) int rgb_in, rgb_out, out_mode = 0;
if (!in_info || !out_info || !color_space_mode)
return; return;
*color_space_mode = 0; rgb_in = in_info->pix_desc->flags & AV_PIX_FMT_FLAG_RGB;
rgb_out = out_info->pix_desc->flags & AV_PIX_FMT_FLAG_RGB;
/* rgb2yuv */ /* rgb2yuv */
if ((in_info->pix_desc->flags & AV_PIX_FMT_FLAG_RGB) && if (rgb_in && !rgb_out) {
!(out_info->pix_desc->flags & AV_PIX_FMT_FLAG_RGB)) {
/* rgb full -> yuv full/limit */ /* rgb full -> yuv full/limit */
if (in->color_range == AVCOL_RANGE_JPEG) { if (in_rng == AVCOL_RANGE_JPEG) {
switch (in->colorspace) { if ((out_rng && *out_rng == AVCOL_RANGE_JPEG) ||
case AVCOL_SPC_BT709: (out_spc && *out_spc == AVCOL_SPC_BT470BG)) {
out->colorspace = AVCOL_SPC_BT709; if (out_spc)
*color_space_mode = 0xb << 8; /* rgb2yuv_709_limit */ *out_spc = AVCOL_SPC_BT470BG;
break;
case AVCOL_SPC_BT470BG:
out->colorspace = AVCOL_SPC_BT470BG;
*color_space_mode = 2 << 2; /* IM_RGB_TO_YUV_BT601_LIMIT */
break;
}
}
if (*color_space_mode) {
out->color_trc = AVCOL_TRC_UNSPECIFIED;
out->color_primaries = AVCOL_PRI_UNSPECIFIED;
out->color_range = AVCOL_RANGE_MPEG;
}
}
if (out_rng && *out_rng == AVCOL_RANGE_JPEG)
out_mode = 1 << 2; /* IM_RGB_TO_YUV_BT601_FULL */
else {
if (out_rng)
*out_rng = AVCOL_RANGE_MPEG;
out_mode = 2 << 2; /* IM_RGB_TO_YUV_BT601_LIMIT */
}
} else {
if (out_spc)
*out_spc = AVCOL_SPC_BT709;
if (out_rng)
*out_rng = AVCOL_RANGE_MPEG;
out_mode = is_rga2_used ? (0xb << 8) /* rgb2yuv_709_limit */
: (3 << 2); /* IM_RGB_TO_YUV_BT709_LIMIT */
}
}
if (out_mode)
*color_space_mode |= out_mode;
}
/* yuv2rgb */ /* yuv2rgb */
if (!(in_info->pix_desc->flags & AV_PIX_FMT_FLAG_RGB) && else if (!rgb_in && rgb_out) {
(out_info->pix_desc->flags & AV_PIX_FMT_FLAG_RGB)) {
/* yuv full/limit -> rgb full */ /* yuv full/limit -> rgb full */
switch (in->color_range) { switch (in_rng) {
case AVCOL_RANGE_MPEG: case AVCOL_RANGE_MPEG:
if (in->colorspace == AVCOL_SPC_BT709) { if (in_spc == AVCOL_SPC_BT709)
out->colorspace = AVCOL_SPC_BT709; out_mode = 3 << 0; /* IM_YUV_TO_RGB_BT709_LIMIT */
*color_space_mode = 3 << 0; /* IM_YUV_TO_RGB_BT709_LIMIT */ if (in_spc == AVCOL_SPC_BT470BG)
} out_mode = 1 << 0; /* IM_YUV_TO_RGB_BT601_LIMIT */
if (in->colorspace == AVCOL_SPC_BT470BG) {
out->colorspace = AVCOL_SPC_BT470BG;
*color_space_mode = 1 << 0; /* IM_YUV_TO_RGB_BT601_LIMIT */
}
break; break;
case AVCOL_RANGE_JPEG: case AVCOL_RANGE_JPEG:
#if 0 #if 0
if (in->colorspace == AVCOL_SPC_BT709) { if (in_spc == AVCOL_SPC_BT709)
out->colorspace = AVCOL_SPC_BT709; out_mode = 0xc << 8; /* yuv2rgb_709_full */
*color_space_mode = 0xc << 8; /* yuv2rgb_709_full */ if (in_spc == AVCOL_SPC_BT470BG)
}
#endif #endif
if (in->colorspace == AVCOL_SPC_BT470BG) { out_mode = 2 << 0; /* IM_YUV_TO_RGB_BT601_FULL */
out->colorspace = AVCOL_SPC_BT470BG;
*color_space_mode = 2 << 0; /* IM_YUV_TO_RGB_BT601_FULL */
}
break; break;
} }
if (*color_space_mode) { if (out_spc)
out->color_trc = AVCOL_TRC_UNSPECIFIED; *out_spc = AVCOL_SPC_RGB;
out->color_primaries = AVCOL_PRI_UNSPECIFIED; if (out_rng)
out->color_range = AVCOL_RANGE_JPEG; *out_rng = AVCOL_RANGE_JPEG;
} if (out_mode)
*color_space_mode |= out_mode;
}
/* passthrough */
else {
if (out_spc)
*out_spc = in_spc;
if (out_rng)
*out_rng = in_rng;
} }
/* yuvj2yuv */ /* yuvj2yuv */
if ((in_info->pix_fmt == AV_PIX_FMT_YUVJ420P || if ((in_info->pix_fmt == AV_PIX_FMT_YUVJ420P ||
in_info->pix_fmt == AV_PIX_FMT_YUVJ422P) && in_info->pix_fmt == AV_PIX_FMT_YUVJ422P) && !rgb_out) {
!(out_info->pix_desc->flags & AV_PIX_FMT_FLAG_RGB)) { if (out_rng)
out->color_range = AVCOL_RANGE_JPEG; *out_rng = AVCOL_RANGE_JPEG;
} }
} }
@@ -391,7 +403,7 @@ static int verify_rga_frame_info_io_dynamic(AVFilterContext *avctx,
} }
static RGAFrame *submit_frame(RKRGAContext *r, AVFilterLink *inlink, static RGAFrame *submit_frame(RKRGAContext *r, AVFilterLink *inlink,
AVFrame *picref, int do_overlay, int pat_preproc) const AVFrame *picref, int do_overlay, int pat_preproc)
{ {
RGAFrame *rga_frame; RGAFrame *rga_frame;
AVFilterContext *ctx = inlink->dst; AVFilterContext *ctx = inlink->dst;
@@ -532,7 +544,7 @@ static RGAFrame *submit_frame(RKRGAContext *r, AVFilterLink *inlink,
} }
static RGAFrame *query_frame(RKRGAContext *r, AVFilterLink *outlink, static RGAFrame *query_frame(RKRGAContext *r, AVFilterLink *outlink,
const AVFrame *in, int pat_preproc) const AVFrame *in, const AVFrame *picref_pat, int pat_preproc)
{ {
AVFilterContext *ctx = outlink->src; AVFilterContext *ctx = outlink->src;
AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *inlink = ctx->inputs[0];
@@ -611,8 +623,29 @@ static RGAFrame *query_frame(RKRGAContext *r, AVFilterLink *outlink,
if (out_info->uncompact_10b_msb) if (out_info->uncompact_10b_msb)
info.is_10b_compact = info.is_10b_endian = 1; info.is_10b_compact = info.is_10b_endian = 1;
if (!pat_preproc) if (!pat_preproc) {
set_colorspace_info(in0_info, in, out_info, out_frame->frame, &info.color_space_mode); int is_rga2_used = r->is_rga2_used || out_info->scheduler_core == (out_info->scheduler_core & 0xc);
#ifdef RGA_NORMAL_DST_FULL_CSC_FIXUP
if (in1_info && picref_pat) {
enum AVColorSpace pat_colorspace = picref_pat->colorspace;
enum AVColorRange pat_color_range = picref_pat->color_range;
/* yuv2rgb src->pat */
set_colorspace_info(in0_info, in->colorspace, in->color_range,
in1_info, &pat_colorspace, &pat_color_range,
&info.color_space_mode, is_rga2_used);
/* rgb2yuv pat->dst */
set_colorspace_info(in1_info, pat_colorspace, pat_color_range,
out_info, &out_frame->frame->colorspace, &out_frame->frame->color_range,
&info.color_space_mode, is_rga2_used);
} else
#endif
{
set_colorspace_info(in0_info, in->colorspace, in->color_range,
out_info, &out_frame->frame->colorspace, &out_frame->frame->color_range,
&info.color_space_mode, is_rga2_used);
}
}
if (pat_preproc) if (pat_preproc)
rga_set_rect(&info.rect, in1_info->overlay_x, in1_info->overlay_y, rga_set_rect(&info.rect, in1_info->overlay_x, in1_info->overlay_y,
@@ -1223,8 +1256,8 @@ static int call_rkrga_blit(AVFilterContext *avctx,
#define PRINT_RGA_INFO(ctx, info, name) do { \ #define PRINT_RGA_INFO(ctx, info, name) do { \
if (info && name) \ if (info && name) \
av_log(ctx, AV_LOG_DEBUG, "RGA %s | fd:%d mmu:%d rd_mode:%d | x:%d y:%d w:%d h:%d ws:%d hs:%d fmt:0x%x\n", \ av_log(ctx, AV_LOG_DEBUG, "RGA %s | fd:%d mmu:%d rd:%d csc:%d | x:%d y:%d w:%d h:%d ws:%d hs:%d fmt:0x%x\n", \
name, info->fd, info->mmuFlag, (info->rd_mode >> 1), info->rect.xoffset, info->rect.yoffset, \ name, info->fd, info->mmuFlag, (info->rd_mode >> 1), info->color_space_mode, info->rect.xoffset, info->rect.yoffset, \
info->rect.width, info->rect.height, info->rect.wstride, info->rect.hstride, (info->rect.format >> 8)); \ info->rect.width, info->rect.height, info->rect.wstride, info->rect.hstride, (info->rect.format >> 8)); \
} while (0) } while (0)
@@ -1290,7 +1323,7 @@ int ff_rkrga_filter_frame(RKRGAContext *r,
} }
/* DST */ /* DST */
if (!(dst_frame = query_frame(r, outlink, src_frame->frame, 0))) { if (!(dst_frame = query_frame(r, outlink, src_frame->frame, picref_pat, 0))) {
av_log(ctx, AV_LOG_ERROR, "Failed to query an output frame\n"); av_log(ctx, AV_LOG_ERROR, "Failed to query an output frame\n");
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
} }
@@ -1313,7 +1346,7 @@ int ff_rkrga_filter_frame(RKRGAContext *r,
FF_INLINK_IDX(inlink_pat)); FF_INLINK_IDX(inlink_pat));
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
} }
if (!(pat_out = query_frame(r, outlink, picref_pat, 1))) { if (!(pat_out = query_frame(r, outlink, picref_pat, NULL, 1))) {
av_log(ctx, AV_LOG_ERROR, "Failed to query an output frame\n"); av_log(ctx, AV_LOG_ERROR, "Failed to query an output frame\n");
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
} }