lavc/rkmppenc: add chroma_fmt option for MJPEG encoder

Signed-off-by: nyanmisaka <nst799610810@gmail.com>
This commit is contained in:
nyanmisaka
2025-05-31 18:13:23 +08:00
parent bdcd952b12
commit 5ab1a0b7ba
2 changed files with 72 additions and 0 deletions

View File

@@ -73,9 +73,19 @@ static MppFrameFormat rkmpp_get_mpp_fmt_mjpeg(enum AVPixelFormat pix_fmt)
switch (pix_fmt) {
case AV_PIX_FMT_YUVJ420P:
case AV_PIX_FMT_YUV420P: return MPP_FMT_YUV420P;
case AV_PIX_FMT_YUVJ422P:
case AV_PIX_FMT_YUV422P: return MPP_FMT_YUV422P; /* RK3576+ only */
case AV_PIX_FMT_YUVJ444P:
case AV_PIX_FMT_YUV444P: return MPP_FMT_YUV444P; /* RK3576+ only */
case AV_PIX_FMT_NV12: return MPP_FMT_YUV420SP;
case AV_PIX_FMT_NV21: return MPP_FMT_YUV420SP_VU; /* RK3576+ only */
case AV_PIX_FMT_NV16: return MPP_FMT_YUV422SP; /* RK3576+ only */
case AV_PIX_FMT_NV24: return MPP_FMT_YUV444SP; /* RK3576+ only */
case AV_PIX_FMT_YUYV422: return MPP_FMT_YUV422_YUYV;
case AV_PIX_FMT_UYVY422: return MPP_FMT_YUV422_UYVY;
case AV_PIX_FMT_YVYU422: return MPP_FMT_YUV422_YVYU; /* RK3576+ only */
/* RGB: pre-RK3576 only */
case AV_PIX_FMT_RGB444BE: return MPP_FMT_RGB444;
case AV_PIX_FMT_BGR444BE: return MPP_FMT_BGR444;
case AV_PIX_FMT_RGB555BE: return MPP_FMT_RGB555;
@@ -105,6 +115,38 @@ static uint32_t rkmpp_get_drm_afbc_format(MppFrameFormat mpp_fmt)
}
}
static MppFrameChromaFormat rkmpp_fix_chroma_fmt(int chroma_fmt,
enum AVPixelFormat pix_fmt)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
int log2_chroma_sum = desc->log2_chroma_w + desc->log2_chroma_h;
int is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) &&
desc->nb_components >= 2;
if (!is_yuv)
return MPP_CHROMA_UNSPECIFIED;
switch (chroma_fmt) {
case -1:
return log2_chroma_sum == 0 ? MPP_CHROMA_444 :
log2_chroma_sum == 1 ? MPP_CHROMA_422 :
MPP_CHROMA_UNSPECIFIED;
case MPP_CHROMA_400:
return chroma_fmt;
case MPP_CHROMA_420:
return log2_chroma_sum <= 2 ?
chroma_fmt : MPP_CHROMA_UNSPECIFIED;
case MPP_CHROMA_422:
return log2_chroma_sum <= 1 ?
chroma_fmt : MPP_CHROMA_UNSPECIFIED;
case MPP_CHROMA_444:
return log2_chroma_sum == 0 ?
chroma_fmt : MPP_CHROMA_UNSPECIFIED;
default:
return MPP_CHROMA_UNSPECIFIED;
}
}
static int get_byte_stride(const AVDRMObjectDescriptor *object,
const AVDRMLayerDescriptor *layer,
int is_rgb, int is_planar,
@@ -310,6 +352,12 @@ static int rkmpp_set_enc_cfg_prep(AVCodecContext *avctx, AVFrame *frame)
mpp_enc_cfg_set_s32(cfg, "prep:colorrange", AVCOL_RANGE_JPEG);
}
if (avctx->codec_id == AV_CODEC_ID_MJPEG) {
/* always output full range if the MJPEG encoder supports CSC */
mpp_enc_cfg_set_s32(cfg, "prep:range_out", AVCOL_RANGE_JPEG);
mpp_enc_cfg_set_s32(cfg, "prep:format_out", rkmpp_fix_chroma_fmt(r->chroma_fmt, r->pix_fmt));
}
if (is_afbc) {
const AVDRMLayerDescriptor *layer = &drm_desc->layers[0];
uint32_t drm_afbc_fmt = rkmpp_get_drm_afbc_format(mpp_fmt);
@@ -368,6 +416,12 @@ static int rkmpp_set_enc_cfg(AVCodecContext *avctx)
mpp_enc_cfg_set_s32(cfg, "prep:colorrange", AVCOL_RANGE_JPEG);
}
if (avctx->codec_id == AV_CODEC_ID_MJPEG) {
/* always output full range if the MJPEG encoder supports CSC */
mpp_enc_cfg_set_s32(cfg, "prep:range_out", AVCOL_RANGE_JPEG);
mpp_enc_cfg_set_s32(cfg, "prep:format_out", rkmpp_fix_chroma_fmt(r->chroma_fmt, r->pix_fmt));
}
if (avctx->framerate.den > 0 && avctx->framerate.num > 0)
av_reduce(&fps_num, &fps_den, avctx->framerate.num, avctx->framerate.den, 65535);
else

View File

@@ -82,6 +82,7 @@ typedef struct RKMPPEncContext {
int dct8x8;
int udu_sei;
int prefix_mode;
int chroma_fmt;
} RKMPPEncContext;
static const AVRational mpp_tb = { 1, 1000000 };
@@ -190,6 +191,13 @@ static const AVOption mjpeg_options[] = {
{ .i64 = -1 }, -1, 99, VE, "qp_max" }, \
{ "qp_min", "Set the min QP/Q_Factor value", OFFSET(qp_min), AV_OPT_TYPE_INT, \
{ .i64 = -1 }, -1, 99, VE, "qp_min" }, \
{ "chroma_fmt", "Specify the output chroma format for down subsampling", OFFSET(chroma_fmt), AV_OPT_TYPE_INT, \
{ .i64 = MPP_CHROMA_UNSPECIFIED }, -1, MPP_CHROMA_444, VE, .unit = "chroma_fmt" }, \
{ "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, 0, 0, VE, .unit = "chroma_fmt" },
{ "400", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MPP_CHROMA_400 }, 0, 0, VE, .unit = "chroma_fmt" },
{ "420", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MPP_CHROMA_420 }, 0, 0, VE, .unit = "chroma_fmt" },
{ "422", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MPP_CHROMA_422 }, 0, 0, VE, .unit = "chroma_fmt" },
{ "444", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MPP_CHROMA_444 }, 0, 0, VE, .unit = "chroma_fmt" },
{ NULL },
};
@@ -225,9 +233,19 @@ static const enum AVPixelFormat rkmpp_enc_pix_fmts_h26x[] = {
static const enum AVPixelFormat rkmpp_enc_pix_fmts_mjpeg[] = {
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_YUVJ420P,
AV_PIX_FMT_YUV422P, /* RK3576+ only */
AV_PIX_FMT_YUVJ422P,
AV_PIX_FMT_YUV444P, /* RK3576+ only */
AV_PIX_FMT_YUVJ444P,
AV_PIX_FMT_NV12,
AV_PIX_FMT_NV21, /* RK3576+ only */
AV_PIX_FMT_NV16, /* RK3576+ only */
AV_PIX_FMT_NV24, /* RK3576+ only */
AV_PIX_FMT_YUYV422,
AV_PIX_FMT_UYVY422,
AV_PIX_FMT_YVYU422, /* RK3576+ only */
/* RGB: pre-RK3576 only */
AV_PIX_FMT_RGB444BE,
AV_PIX_FMT_BGR444BE,
AV_PIX_FMT_RGB555BE,