fixup! lavc/rkmppdec: refactor RKMPP decoders and extend codecs

add initial support for rk3576

Signed-off-by: nyanmisaka <nst799610810@gmail.com>
This commit is contained in:
nyanmisaka
2024-10-16 16:28:16 +08:00
parent f7617540aa
commit 4eea7f7fe3
2 changed files with 81 additions and 13 deletions

View File

@@ -30,6 +30,8 @@
#include "rkmppdec.h" #include "rkmppdec.h"
#include <fcntl.h>
#include <unistd.h>
#if CONFIG_RKRGA #if CONFIG_RKRGA
#include <rga/im2d.h> #include <rga/im2d.h>
#endif #endif
@@ -57,6 +59,7 @@ static uint32_t rkmpp_get_drm_format(MppFrameFormat mpp_fmt)
case MPP_FMT_YUV420SP_10BIT: return DRM_FORMAT_NV15; case MPP_FMT_YUV420SP_10BIT: return DRM_FORMAT_NV15;
case MPP_FMT_YUV422SP: return DRM_FORMAT_NV16; case MPP_FMT_YUV422SP: return DRM_FORMAT_NV16;
case MPP_FMT_YUV422SP_10BIT: return DRM_FORMAT_NV20; case MPP_FMT_YUV422SP_10BIT: return DRM_FORMAT_NV20;
case MPP_FMT_YUV444SP: return DRM_FORMAT_NV24;
default: return DRM_FORMAT_INVALID; default: return DRM_FORMAT_INVALID;
} }
} }
@@ -68,6 +71,7 @@ static uint32_t rkmpp_get_drm_afbc_format(MppFrameFormat mpp_fmt)
case MPP_FMT_YUV420SP_10BIT: return DRM_FORMAT_YUV420_10BIT; case MPP_FMT_YUV420SP_10BIT: return DRM_FORMAT_YUV420_10BIT;
case MPP_FMT_YUV422SP: return DRM_FORMAT_YUYV; case MPP_FMT_YUV422SP: return DRM_FORMAT_YUYV;
case MPP_FMT_YUV422SP_10BIT: return DRM_FORMAT_Y210; case MPP_FMT_YUV422SP_10BIT: return DRM_FORMAT_Y210;
case MPP_FMT_YUV444SP: return DRM_FORMAT_VUY888;
default: return DRM_FORMAT_INVALID; default: return DRM_FORMAT_INVALID;
} }
} }
@@ -79,6 +83,7 @@ static uint32_t rkmpp_get_av_format(MppFrameFormat mpp_fmt)
case MPP_FMT_YUV420SP_10BIT: return AV_PIX_FMT_NV15; case MPP_FMT_YUV420SP_10BIT: return AV_PIX_FMT_NV15;
case MPP_FMT_YUV422SP: return AV_PIX_FMT_NV16; case MPP_FMT_YUV422SP: return AV_PIX_FMT_NV16;
case MPP_FMT_YUV422SP_10BIT: return AV_PIX_FMT_NV20; case MPP_FMT_YUV422SP_10BIT: return AV_PIX_FMT_NV20;
case MPP_FMT_YUV444SP: return AV_PIX_FMT_NV24;
default: return AV_PIX_FMT_NONE; default: return AV_PIX_FMT_NONE;
} }
} }
@@ -107,6 +112,35 @@ static int get_afbc_byte_stride(const AVPixFmtDescriptor *desc,
return (*stride > 0) ? 0 : AVERROR(EINVAL); return (*stride > 0) ? 0 : AVERROR(EINVAL);
} }
static void read_soc_name(AVCodecContext *avctx, char *name, int size)
{
const char *dt_path = "/proc/device-tree/compatible";
int fd = open(dt_path, O_RDONLY);
if (fd < 0) {
av_log(avctx, AV_LOG_VERBOSE, "Unable to open '%s' for reading SoC name\n", dt_path);
} else {
ssize_t soc_name_len = 0;
snprintf(name, size - 1, "unknown");
soc_name_len = read(fd, name, size - 1);
if (soc_name_len > 0) {
name[soc_name_len] = '\0';
/* replacing the termination character to space */
for (char *ptr = name;; ptr = name) {
ptr += av_strnlen(name, size);
if (ptr >= name + soc_name_len - 1)
break;
*ptr = ' ';
}
av_log(avctx, AV_LOG_VERBOSE, "Found SoC name from device-tree: '%s'\n", name);
}
close(fd);
}
}
static av_cold int rkmpp_decode_close(AVCodecContext *avctx) static av_cold int rkmpp_decode_close(AVCodecContext *avctx)
{ {
RKMPPDecContext *r = avctx->priv_data; RKMPPDecContext *r = avctx->priv_data;
@@ -116,6 +150,7 @@ static av_cold int rkmpp_decode_close(AVCodecContext *avctx)
r->info_change = 0; r->info_change = 0;
r->errinfo_cnt = 0; r->errinfo_cnt = 0;
r->got_frame = 0; r->got_frame = 0;
r->use_rfbc = 0;
if (r->mapi) { if (r->mapi) {
r->mapi->reset(r->mctx); r->mapi->reset(r->mctx);
@@ -141,6 +176,7 @@ static av_cold int rkmpp_decode_init(AVCodecContext *avctx)
RKMPPDecContext *r = avctx->priv_data; RKMPPDecContext *r = avctx->priv_data;
MppCodingType coding_type = MPP_VIDEO_CodingUnused; MppCodingType coding_type = MPP_VIDEO_CodingUnused;
const char *opts_env = NULL; const char *opts_env = NULL;
char soc_name[MAX_SOC_NAME_LENGTH];
int ret, is_fmt_supported = 0; int ret, is_fmt_supported = 0;
enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_DRM_PRIME, enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_DRM_PRIME,
AV_PIX_FMT_NV12, AV_PIX_FMT_NV12,
@@ -153,9 +189,11 @@ static av_cold int rkmpp_decode_init(AVCodecContext *avctx)
switch (avctx->pix_fmt) { switch (avctx->pix_fmt) {
case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUV420P:
case AV_PIX_FMT_YUVJ420P: case AV_PIX_FMT_YUVJ420P:
pix_fmts[1] = AV_PIX_FMT_NV12;
is_fmt_supported = 1; is_fmt_supported = 1;
break; break;
case AV_PIX_FMT_YUV420P10: case AV_PIX_FMT_YUV420P10:
pix_fmts[1] = AV_PIX_FMT_NV15;
is_fmt_supported = is_fmt_supported =
avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_H264 ||
avctx->codec_id == AV_CODEC_ID_HEVC || avctx->codec_id == AV_CODEC_ID_HEVC ||
@@ -163,10 +201,20 @@ static av_cold int rkmpp_decode_init(AVCodecContext *avctx)
avctx->codec_id == AV_CODEC_ID_AV1; avctx->codec_id == AV_CODEC_ID_AV1;
break; break;
case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUV422P:
case AV_PIX_FMT_YUV422P10: pix_fmts[1] = AV_PIX_FMT_NV16;
is_fmt_supported = is_fmt_supported =
avctx->codec_id == AV_CODEC_ID_H264; avctx->codec_id == AV_CODEC_ID_H264;
break; break;
case AV_PIX_FMT_YUV422P10:
pix_fmts[1] = AV_PIX_FMT_NV20;
is_fmt_supported =
avctx->codec_id == AV_CODEC_ID_H264;
break;
case AV_PIX_FMT_YUV444P:
pix_fmts[1] = AV_PIX_FMT_NV24;
is_fmt_supported =
avctx->codec_id == AV_CODEC_ID_HEVC;
break;
case AV_PIX_FMT_NONE: /* fallback to drm_prime */ case AV_PIX_FMT_NONE: /* fallback to drm_prime */
is_fmt_supported = 1; is_fmt_supported = 1;
avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME; avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
@@ -225,16 +273,27 @@ static av_cold int rkmpp_decode_init(AVCodecContext *avctx)
if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME)
r->afbc = 0; r->afbc = 0;
if (r->afbc > RKMPP_DEC_AFBC_OFF) {
read_soc_name(avctx, soc_name, sizeof(soc_name));
r->use_rfbc = !!strstr(soc_name, "rk3576");
}
if (r->afbc == RKMPP_DEC_AFBC_ON_RGA) { if (r->afbc == RKMPP_DEC_AFBC_ON_RGA) {
#if CONFIG_RKRGA #if CONFIG_RKRGA
const char *rga_ver = querystring(RGA_VERSION); const char *rga_ver = querystring(RGA_VERSION);
int has_rga2p = !!strstr(rga_ver, "RGA_2_PRO");
int has_rga3 = !!strstr(rga_ver, "RGA_3"); int has_rga3 = !!strstr(rga_ver, "RGA_3");
int is_rga2p_compat = avctx->width >= 2 &&
avctx->width <= 8192 &&
avctx->height >= 2 &&
avctx->height <= 8192;
int is_rga3_compat = avctx->width >= 68 && int is_rga3_compat = avctx->width >= 68 &&
avctx->width <= 8176 && avctx->width <= 8176 &&
avctx->height >= 2 && avctx->height >= 2 &&
avctx->height <= 8176; avctx->height <= 8176;
if (!has_rga3 || !is_rga3_compat) { r->use_rfbc = r->use_rfbc || has_rga2p;
if (!((has_rga2p && is_rga2p_compat) || (has_rga3 && is_rga3_compat))) {
#endif #endif
av_log(avctx, AV_LOG_VERBOSE, "AFBC is requested without capable RGA, ignoring\n"); av_log(avctx, AV_LOG_VERBOSE, "AFBC is requested without capable RGA, ignoring\n");
r->afbc = RKMPP_DEC_AFBC_OFF; r->afbc = RKMPP_DEC_AFBC_OFF;
@@ -290,6 +349,7 @@ static int rkmpp_set_buffer_group(AVCodecContext *avctx,
{ {
RKMPPDecContext *r = avctx->priv_data; RKMPPDecContext *r = avctx->priv_data;
AVHWFramesContext *hwfc = NULL; AVHWFramesContext *hwfc = NULL;
AVRKMPPFramesContext *rkmpp_fc = NULL;
int i, ret, decoder_pool_size; int i, ret, decoder_pool_size;
if (!r->hwdevice) if (!r->hwdevice)
@@ -317,15 +377,15 @@ static int rkmpp_set_buffer_group(AVCodecContext *avctx,
hwfc->width = FFALIGN(width, 16); hwfc->width = FFALIGN(width, 16);
hwfc->height = FFALIGN(height, 16); hwfc->height = FFALIGN(height, 16);
if (r->buf_mode == RKMPP_DEC_HALF_INTERNAL) { rkmpp_fc = hwfc->hwctx;
AVRKMPPFramesContext *rkmpp_fc = NULL; rkmpp_fc->flags |= MPP_BUFFER_FLAGS_CACHABLE;
if (r->buf_mode == RKMPP_DEC_HALF_INTERNAL) {
if ((ret = av_hwframe_ctx_init(r->hwframe)) < 0) { if ((ret = av_hwframe_ctx_init(r->hwframe)) < 0) {
av_log(avctx, AV_LOG_ERROR, "Failed to init RKMPP frame pool\n"); av_log(avctx, AV_LOG_ERROR, "Failed to init RKMPP frame pool\n");
goto fail; goto fail;
} }
rkmpp_fc = hwfc->hwctx;
r->buf_group = rkmpp_fc->buf_group; r->buf_group = rkmpp_fc->buf_group;
goto attach; goto attach;
} else if (r->buf_mode != RKMPP_DEC_PURE_EXTERNAL) { } else if (r->buf_mode != RKMPP_DEC_PURE_EXTERNAL) {
@@ -539,7 +599,8 @@ static int rkmpp_export_frame(AVCodecContext *avctx, AVFrame *frame, MppFrame mp
if (is_afbc) { if (is_afbc) {
desc->drm_desc.objects[0].format_modifier = desc->drm_desc.objects[0].format_modifier =
DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_BLOCK_SIZE_16x16); r->use_rfbc ? DRM_FORMAT_MOD_ROCKCHIP_RFBC(ROCKCHIP_RFBC_BLOCK_SIZE_64x4)
: DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_BLOCK_SIZE_16x16);
layer->format = rkmpp_get_drm_afbc_format(mpp_fmt); layer->format = rkmpp_get_drm_afbc_format(mpp_fmt);
layer->nb_planes = 1; layer->nb_planes = 1;
@@ -551,7 +612,7 @@ static int rkmpp_export_frame(AVCodecContext *avctx, AVFrame *frame, MppFrame mp
return ret; return ret;
/* MPP specific AFBC src_y offset, not memory address offset */ /* MPP specific AFBC src_y offset, not memory address offset */
frame->crop_top = mpp_frame_get_offset_y(mpp_frame); frame->crop_top = r->use_rfbc ? 0 : mpp_frame_get_offset_y(mpp_frame);
} else { } else {
layer->format = rkmpp_get_drm_format(mpp_fmt); layer->format = rkmpp_get_drm_format(mpp_fmt);
layer->nb_planes = 2; layer->nb_planes = 2;
@@ -561,6 +622,9 @@ static int rkmpp_export_frame(AVCodecContext *avctx, AVFrame *frame, MppFrame mp
layer->planes[1].object_index = 0; layer->planes[1].object_index = 0;
layer->planes[1].offset = layer->planes[0].pitch * mpp_frame_get_ver_stride(mpp_frame); layer->planes[1].offset = layer->planes[0].pitch * mpp_frame_get_ver_stride(mpp_frame);
layer->planes[1].pitch = layer->planes[0].pitch; layer->planes[1].pitch = layer->planes[0].pitch;
if (avctx->sw_pix_fmt == AV_PIX_FMT_NV24)
layer->planes[1].pitch *= 2;
} }
if ((ret = frame_create_buf(frame, mpp_frame, mpp_frame_get_buf_size(mpp_frame), if ((ret = frame_create_buf(frame, mpp_frame, mpp_frame_get_buf_size(mpp_frame),
@@ -767,6 +831,7 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout)
break; break;
case AV_PIX_FMT_NV12: case AV_PIX_FMT_NV12:
case AV_PIX_FMT_NV16: case AV_PIX_FMT_NV16:
case AV_PIX_FMT_NV24:
case AV_PIX_FMT_NV15: case AV_PIX_FMT_NV15:
case AV_PIX_FMT_NV20: case AV_PIX_FMT_NV20:
{ {

View File

@@ -35,12 +35,14 @@
#include "hwconfig.h" #include "hwconfig.h"
#include "internal.h" #include "internal.h"
#include "libavutil/avstring.h"
#include "libavutil/hwcontext_rkmpp.h" #include "libavutil/hwcontext_rkmpp.h"
#include "libavutil/mastering_display_metadata.h" #include "libavutil/mastering_display_metadata.h"
#include "libavutil/opt.h" #include "libavutil/opt.h"
#include "libavutil/pixdesc.h" #include "libavutil/pixdesc.h"
#define MAX_ERRINFO_COUNT 100 #define MAX_ERRINFO_COUNT 100
#define MAX_SOC_NAME_LENGTH 128
typedef struct RKMPPDecContext { typedef struct RKMPPDecContext {
AVClass *class; AVClass *class;
@@ -58,6 +60,7 @@ typedef struct RKMPPDecContext {
int info_change; int info_change;
int errinfo_cnt; int errinfo_cnt;
int got_frame; int got_frame;
int use_rfbc;
int deint; int deint;
int afbc; int afbc;