diff --git a/inc/rk_mpi_cmd.h b/inc/rk_mpi_cmd.h index c0b894c8..758436a4 100644 --- a/inc/rk_mpi_cmd.h +++ b/inc/rk_mpi_cmd.h @@ -131,6 +131,7 @@ typedef enum { MPP_ENC_PRE_ALLOC_BUFF, /* allocate buffers before encoding */ MPP_ENC_SET_QP_RANGE, /* used for adjusting qp range, the parameter can be 1 or 2 */ MPP_ENC_SET_ROI_CFG, /* set MppEncROICfg structure */ + MPP_ENC_SET_CTU_QP, /* for H265 Encoder,set CTU's size and QP */ MPP_ENC_CMD_END, MPP_ISP_CMD_BASE = CMD_MODULE_CODEC | CMD_CTX_ID_ISP, @@ -811,6 +812,77 @@ typedef struct MppEncH264Cfg_t { MppEncH264RefCfg ref; } MppEncH264Cfg; + +#define H265E_MAX_ROI_NUMBER 64 +typedef struct H265eRect_t { + RK_S32 left; + RK_S32 right; + RK_S32 top; + RK_S32 bottom; +} H265eRect; + +typedef struct H265eRoi_Region_t { + RK_U8 level; + H265eRect rect; +} H265eRoiRegion; + +/* + * roi region only can be setting when rc_enable = 1 + */ +typedef struct MppEncH265RoiCfg_t { + /* + * the value is defined by H265eCtuMethod + */ + + RK_U8 method; + /* + * the number of roi,the value must less than H265E_MAX_ROI_NUMBER + */ + RK_S32 num; + + /* delat qp using in roi region*/ + RK_U32 delta_qp; + + /* roi region */ + H265eRoiRegion region[H265E_MAX_ROI_NUMBER]; +} MppEncH265RoiCfg; + +typedef struct H265eCtuQp_t { + /* the qp value using in ctu region */ + RK_U32 qp; + + /* + * define the ctu region + * method = H265E_METHOD_CUT_SIZE, the value of rect is in ctu size + * method = H264E_METHOD_COORDINATE,the value of rect is in coordinates + */ + H265eRect rect; +} H265eCtu; + +typedef struct H265eCtuRegion_t { + /* + * the value is defined by H265eCtuMethod + */ + RK_U8 method; + + /* + * the number of ctu,the value must less than H265E_MAX_ROI_NUMBER + */ + RK_S32 num; + + /* ctu region */ + H265eCtu ctu[H265E_MAX_ROI_NUMBER]; +} MppEncH265CtuCfg; + +/* + * define the method when set CTU/ROI parameters + * this value is using by method in H265eCtuRegion or H265eRoi struct + */ +typedef enum { + H265E_METHOD_CTU_SIZE, + H264E_METHOD_COORDINATE, +} H265eCtuMethod; + /* * H.265 configurable parameter */ @@ -827,6 +899,23 @@ typedef struct MppEncH265SeiCfg_t { RK_U32 change; } MppEncH265SeiCfg; + +typedef enum MppEncH265CfgChange_e { + /* change on stream type */ + MPP_ENC_H265_CFG_PROFILE_LEVEL_TILER_CHANGE = (1 << 0), + MPP_ENC_H265_CFG_INTRA_QP_CHANGE = (1 << 1), + MPP_ENC_H265_CFG_FRAME_RATE_CHANGE = (1 << 2), + MPP_ENC_H265_CFG_BITRATE_CHANGE = (1 << 3), + MPP_ENC_H265_CFG_GOP_SIZE = (1 << 4), + MPP_ENC_H265_CFG_RC_QP_CHANGE = (1 << 5), + MPP_ENC_H265_CFG_INTRA_REFRESH_CHANGE = (1 << 6), + MPP_ENC_H265_CFG_INDEPEND_SLICE_CHANGE = (1 << 7), + MPP_ENC_H265_CFG_DEPEND_SLICE_CHANGE = (1 << 8), + MPP_ENC_H265_CFG_CTU_CHANGE = (1 << 9), + MPP_ENC_H265_CFG_ROI_CHANGE = (1 << 10), + MPP_ENC_H265_CFG_CHANGE_ALL = (0xFFFFFFFF), +} MppEncH265CfgChange; + typedef struct MppEncH265Cfg_t { RK_U32 change; @@ -845,6 +934,8 @@ typedef struct MppEncH265Cfg_t { RK_S32 max_qp; RK_S32 min_qp; RK_S32 max_delta_qp; + RK_S32 intra_qp; + RK_S32 gop_delta_qp; /* intra fresh config */ RK_S32 intra_refresh_mode; @@ -859,6 +950,9 @@ typedef struct MppEncH265Cfg_t { /* extra info */ MppEncH265VuiCfg vui; MppEncH265SeiCfg sei; + + MppEncH265CtuCfg ctu; + MppEncH265RoiCfg roi; } MppEncH265Cfg; /* diff --git a/inc/vpu.h b/inc/vpu.h index 6e24d135..8843ff06 100644 --- a/inc/vpu.h +++ b/inc/vpu.h @@ -50,6 +50,7 @@ typedef enum { VPU_DEC_RKV = 0x5, VPU_ENC_RKV = 0x6, VPU_DEC_AVS = 0x7, + VPU_ENC_H265E = 0x8, VPU_TYPE_BUTT , } VPU_CLIENT_TYPE; diff --git a/inc/vpu_api.h b/inc/vpu_api.h index c29199c4..6435ebcf 100644 --- a/inc/vpu_api.h +++ b/inc/vpu_api.h @@ -92,7 +92,14 @@ typedef enum VPU_API_CMD { VPU_API_GET_FRAME_INFO, VPU_API_SET_OUTPUT_BLOCK, VPU_API_GET_EOS_STATUS, + VPU_API_SET_IMMEDIATE_OUT = 0x1000, + VPU_API_ENC_VEPU22_START = 0x2000, + VPU_API_ENC_SET_VEPU22_CFG, + VPU_API_ENC_GET_VEPU22_CFG, + VPU_API_ENC_SET_VEPU22_CTU_QP, + VPU_API_ENC_SET_VEPU22_ROI, + } VPU_API_CMD; typedef struct { diff --git a/mpp/codec/CMakeLists.txt b/mpp/codec/CMakeLists.txt index e6a903b1..0c26c305 100644 --- a/mpp/codec/CMakeLists.txt +++ b/mpp/codec/CMakeLists.txt @@ -30,6 +30,7 @@ target_link_libraries(mpp_codec ${CODEC_JPEGD} ${CODEC_H264E} ${CODEC_JPEGE} + ${CODEC_H265E} codec_dummy_enc codec_dummy_dec mpp_vproc diff --git a/mpp/codec/enc/CMakeLists.txt b/mpp/codec/enc/CMakeLists.txt index 9a519ce8..66bf9fc2 100644 --- a/mpp/codec/enc/CMakeLists.txt +++ b/mpp/codec/enc/CMakeLists.txt @@ -10,3 +10,7 @@ if(HAVE_JPEGE) add_subdirectory(jpeg) endif() +if(HAVE_H265E) +add_subdirectory(h265) +endif() + diff --git a/mpp/codec/enc/h265/CMakeLists.txt b/mpp/codec/enc/h265/CMakeLists.txt new file mode 100644 index 00000000..06619a63 --- /dev/null +++ b/mpp/codec/enc/h265/CMakeLists.txt @@ -0,0 +1,9 @@ +# vim: syntax=cmake +include_directories(.) + +add_library(${CODEC_H265E} STATIC + h265e_api.c + ) + +target_link_libraries(${CODEC_H265E} mpp_base) +set_target_properties(${CODEC_H265E} PROPERTIES FOLDER "mpp/codec") diff --git a/mpp/codec/enc/h265/h265e_api.c b/mpp/codec/enc/h265/h265e_api.c new file mode 100644 index 00000000..9ec95347 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_api.c @@ -0,0 +1,212 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h265e_api" + +#include + +#include "mpp_err.h" +#include "mpp_log.h" +#include "mpp_env.h" +#include "mpp_common.h" + +#include "h265e_api.h" +#include "h265e_syntax.h" + +#define H265E_DBG_FUNCTION (0x00000001) +#define H265E_DBG_INPUT (0x00000010) +#define H265E_DBG_OUTPUT (0x00000020) + +RK_U32 h265e_debug = 0; + +#define h265e_dbg(flag, fmt, ...) _mpp_dbg(h265e_debug, flag, fmt, ## __VA_ARGS__) +#define h265e_dbg_f(flag, fmt, ...) _mpp_dbg_f(h265e_debug, flag, fmt, ## __VA_ARGS__) + +#define h265e_dbg_func(fmt, ...) h265e_dbg_f(H265E_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define h265e_dbg_input(fmt, ...) h265e_dbg(H265E_DBG_INPUT, fmt, ## __VA_ARGS__) +#define h265e_dbg_output(fmt, ...) h265e_dbg(H265E_DBG_OUTPUT, fmt, ## __VA_ARGS__) + +#define H265E_BIG_ENDIAN 1 +#define H265E_LITTLE_ENDIAN 0 + +typedef struct { + MppEncCfgSet *cfg; + MppEncCfgSet *set; + + H265eSyntax syntax; + H265eFeedback feedback; +} H265eCtx; + +MPP_RET h265e_init(void *ctx, ControllerCfg *ctrlCfg) +{ + H265eCtx *p = (H265eCtx *)ctx; + MppEncCodecCfg *codec = NULL; + if (p == NULL) { + mpp_err_f("error: p == NULL"); + return MPP_NOK; + } + + mpp_assert(ctrlCfg->coding = MPP_VIDEO_CodingHEVC); + p->cfg = ctrlCfg->cfg; + p->set = ctrlCfg->set; + mpp_env_get_u32("h265e_debug", &h265e_debug, 0); + h265e_dbg_func("enter ctx %p\n", ctx); + + memset(&p->syntax, 0, sizeof(p->syntax)); + ctrlCfg->task_count = 1; + + /* set defualt value of codec */ + codec = &p->cfg->codec; + codec->h265.intra_qp = 26; + codec->h265.max_qp = 51; + codec->h265.min_qp = 10; + codec->h265.max_delta_qp = 10; + codec->h265.const_intra_pred = 0; + codec->h265.sao_enable = 1; + codec->h265.gop_delta_qp = 0; + codec->h265.intra_refresh_mode = 0; + codec->h265.intra_refresh_arg = 0; + codec->h265.independ_slice_mode = 0; + codec->h265.independ_slice_arg = 0; + codec->h265.depend_slice_mode = 0; + codec->h265.depend_slice_arg = 0; + + h265e_dbg_func("leave ctx %p\n", ctx); + (void)ctx; + (void)ctrlCfg; + return MPP_OK; +} + +MPP_RET h265e_deinit(void *ctx) +{ + H265eCtx *p = (H265eCtx *)ctx; + if (p == NULL) { + mpp_err_f("error: p == NULL"); + return MPP_NOK; + } + + h265e_dbg_func("enter ctx %p\n", ctx); + h265e_dbg_func("leave ctx %p\n", ctx); + (void)ctx; + return MPP_OK; +} + +MPP_RET h265e_encode(void *ctx, HalEncTask *task) +{ + H265eCtx *p = (H265eCtx *)ctx; + H265eSyntax* syntax = NULL; + if (p == NULL) { + mpp_err_f("error: p == NULL"); + return MPP_NOK; + } + + h265e_dbg_func("enter ctx %p\n", ctx); + syntax = &p->syntax; + + task->valid = 1; +// syntax->eos = task->eos; + task->syntax.data = syntax; + h265e_dbg_func("leave ctx %p\n", ctx); + (void)ctx; + (void)task; + return MPP_OK; +} + +MPP_RET h265e_reset(void *ctx) +{ + H265eCtx *p = (H265eCtx *)ctx; + if (p == NULL) { + mpp_err_f("error: p == NULL"); + return MPP_NOK; + } + + h265e_dbg_func("enter ctx %p\n", ctx); + h265e_dbg_func("leave ctx %p\n", ctx); + (void)ctx; + return MPP_OK; +} + +MPP_RET h265e_flush(void *ctx) +{ + H265eCtx *p = (H265eCtx *)ctx; + if (p == NULL) { + mpp_err_f("error: p == NULL"); + return MPP_NOK; + } + + h265e_dbg_func("enter ctx %p\n", ctx); + h265e_dbg_func("leave ctx %p\n", ctx); + (void)ctx; + return MPP_OK; +} + +MPP_RET h265e_config(void *ctx, RK_S32 cmd, void *param) +{ + H265eCtx *p = (H265eCtx *)ctx; + MPP_RET ret = MPP_NOK; + (void)param; + h265e_dbg_func("enter ctx %p, cmd = %d\n", ctx, cmd); + switch (cmd) { + case SET_IDR_FRAME : { + p->syntax.idr_request++; + } break; + case MPP_ENC_SET_RC_CFG : { + ret = MPP_OK; + } break; + default: + mpp_err("No correspond cmd found, and can not config!"); + ret = MPP_NOK; + break; + } + h265e_dbg_func("leave ctx %p\n", ctx); + return ret; +} + +MPP_RET h265e_callback(void *ctx, void *feedback) +{ + H265eCtx *p = (H265eCtx *)ctx; + H265eFeedback *result = NULL; + H265eFeedback *back = (H265eFeedback*)feedback; + if (p == NULL || feedback == NULL) { + mpp_err_f("error: p == NULL"); + return MPP_NOK; + } + + result = &p->feedback; + h265e_dbg_func("enter ctx %p\n", ctx); + memcpy(result, back, sizeof(H265eFeedback)); + h265e_dbg_func("***********************h265 encoder result************************\n"); + h265e_dbg_func("status size pic_cnt pic_type poc src_idx gop_idx avg_qp\n"); + h265e_dbg_func("[%4d] [%6d] [%4d] [%4d] [%4d] [%4d] [%4d] [%4d]\n", result->status, result->bs_size, + result->enc_pic_cnt, result->pic_type, result->poc, result->src_idx, result->gop_idx, result->avg_ctu_qp); + h265e_dbg_func("******************************************************************\n"); + h265e_dbg_func("leave ctx %p\n", ctx); + return MPP_OK; +} + +const ControlApi api_h265e_controller = { + "h265e_control", + MPP_VIDEO_CodingHEVC, + sizeof(H265eCtx), + 0, + h265e_init, + h265e_deinit, + h265e_encode, + h265e_reset, + h265e_flush, + h265e_config, + h265e_callback, +}; diff --git a/mpp/codec/inc/h265e_api.h b/mpp/codec/inc/h265e_api.h new file mode 100644 index 00000000..efd21012 --- /dev/null +++ b/mpp/codec/inc/h265e_api.h @@ -0,0 +1,32 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __H265E_API_H__ +#define __H265E_API_H__ + +#include "encoder_codec_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const ControlApi api_h265e_controller; + +#ifdef __cplusplus +} +#endif + +#endif /*__H265E_API_H__*/ diff --git a/mpp/codec/mpp_controller.cpp b/mpp/codec/mpp_controller.cpp index 2931f154..51e918a2 100644 --- a/mpp/codec/mpp_controller.cpp +++ b/mpp/codec/mpp_controller.cpp @@ -22,6 +22,7 @@ #include "h264e_api.h" #include "jpege_api.h" +#include "h265e_api.h" #include "mpp_controller.h" /* @@ -34,6 +35,9 @@ static const ControlApi *controllers[] = { #if HAVE_JPEGE &api_jpege_controller, #endif +#if HAVE_H265E + &api_h265e_controller, +#endif }; typedef struct ControllerImpl_t { diff --git a/mpp/codec/mpp_enc.cpp b/mpp/codec/mpp_enc.cpp index ed044e24..3c04242d 100644 --- a/mpp/codec/mpp_enc.cpp +++ b/mpp/codec/mpp_enc.cpp @@ -479,6 +479,10 @@ MPP_RET mpp_enc_control(MppEnc *enc, MpiCmd cmd, void *param) mpp_enc_dbg_ctrl("set qp range\n"); ret = mpp_hal_control(enc->hal, cmd, param); } break; + case MPP_ENC_SET_CTU_QP: { + mpp_enc_dbg_ctrl("set ctu qp\n"); + ret = mpp_hal_control(enc->hal, cmd, param); + } break; default : { mpp_log_f("unsupported cmd id %08x param %p\n", cmd, param); ret = MPP_NOK; diff --git a/mpp/codecs.cmake b/mpp/codecs.cmake index ebbda312..872f43ab 100644 --- a/mpp/codecs.cmake +++ b/mpp/codecs.cmake @@ -99,3 +99,12 @@ if( ENABLE_JPEGE ) set(HAL_JPEGE hal_jpege) add_definitions(-DHAVE_JPEGE) endif() + +# h265 encoder +option(ENABLE_H265E "Enable h265 encoder" ON) +if( ENABLE_H265E ) + set(HAVE_H265E true) + set(CODEC_H265E codec_h265e) + set(HAL_H265E hal_h265e) + add_definitions(-DHAVE_H265E) +endif() diff --git a/mpp/common/h265e_syntax.h b/mpp/common/h265e_syntax.h new file mode 100644 index 00000000..f6b4a1d2 --- /dev/null +++ b/mpp/common/h265e_syntax.h @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __H265E_SYNTAX_H__ +#define __H265E_SYNTAX_H__ + +#include "mpp_frame.h" + +typedef struct H265eSyntax_t { + RK_S32 idr_request; +// RK_S32 eos; +} H265eSyntax; + +typedef struct H265eFeedback_t { + RK_U32 bs_size; + RK_U32 enc_pic_cnt; + RK_U32 pic_type; + RK_U32 avg_ctu_qp; + RK_U32 gop_idx; + RK_U32 poc; + RK_U32 src_idx; + RK_U32 status; +} H265eFeedback; + +#endif diff --git a/mpp/hal/CMakeLists.txt b/mpp/hal/CMakeLists.txt index 8c27c652..611e17cc 100644 --- a/mpp/hal/CMakeLists.txt +++ b/mpp/hal/CMakeLists.txt @@ -40,6 +40,7 @@ target_link_libraries(mpp_hal ${HAL_JPEGD} ${HAL_H264E} ${HAL_JPEGE} + ${HAL_H265E} hal_dummy mpp_device ) diff --git a/mpp/hal/inc/hal_h265e_api.h b/mpp/hal/inc/hal_h265e_api.h new file mode 100644 index 00000000..0cf37d99 --- /dev/null +++ b/mpp/hal/inc/hal_h265e_api.h @@ -0,0 +1,32 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HAL_H265E_API_H__ +#define __HAL_H265E_API_H__ + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_api_h265e; + +#ifdef __cplusplus +} +#endif + +#endif /*__HAL_H265E_API_H__*/ diff --git a/mpp/hal/mpp_hal.cpp b/mpp/hal/mpp_hal.cpp index 0fd9c6e4..5d38122e 100644 --- a/mpp/hal/mpp_hal.cpp +++ b/mpp/hal/mpp_hal.cpp @@ -35,6 +35,7 @@ #include "hal_mpg4d_api.h" #include "hal_jpegd_api.h" #include "hal_jpege_api.h" +#include "hal_h265e_api.h" // for test and demo #include "hal_dummy_dec_api.h" @@ -76,6 +77,9 @@ static const MppHalApi *hw_apis[] = { #endif #if HAVE_JPEGE &hal_api_jpege, +#endif +#if HAVE_H265E + &hal_api_h265e, #endif &hal_api_dummy_dec, &hal_api_dummy_enc, diff --git a/mpp/hal/rkenc/CMakeLists.txt b/mpp/hal/rkenc/CMakeLists.txt index 3db50940..8ea6af44 100644 --- a/mpp/hal/rkenc/CMakeLists.txt +++ b/mpp/hal/rkenc/CMakeLists.txt @@ -1,2 +1,3 @@ # vim: syntax=cmake add_subdirectory(h264e) +add_subdirectory(h265e) diff --git a/mpp/hal/rkenc/h265e/CMakeLists.txt b/mpp/hal/rkenc/h265e/CMakeLists.txt new file mode 100644 index 00000000..6313611e --- /dev/null +++ b/mpp/hal/rkenc/h265e/CMakeLists.txt @@ -0,0 +1,14 @@ +# vim: syntax=cmake +# hal h265e reg + +set(HAL_H265E_SRC + hal_h265e_api.c + hal_h265e_vepu22.c + ) + +add_library(${HAL_H265E} STATIC + ${HAL_H265E_SRC} + ) + +set_target_properties(${HAL_H265E} PROPERTIES FOLDER "mpp/hal") +target_link_libraries(${HAL_H265E} mpp_base) diff --git a/mpp/hal/rkenc/h265e/hal_h265e_api.c b/mpp/hal/rkenc/h265e/hal_h265e_api.c new file mode 100644 index 00000000..7bd8782b --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_api.c @@ -0,0 +1,136 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h265e_api" + +#include + +#include "mpp_env.h" +#include "mpp_log.h" +#include "mpp_common.h" +#include "mpp_platform.h" + +#include "hal_h265e_api.h" +#include "hal_h265e_base.h" +#include "hal_h265e_vepu22.h" + + +RK_U32 hal_h265e_debug = 0; + +MPP_RET hal_h265e_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_NOK; + MppHalApi *p_api = NULL; + + HalH265eCtx* ctx = (HalH265eCtx*)hal; + if (ctx == NULL) { + mpp_err_f("error: ctx == NULL"); + return MPP_NOK; + } + + mpp_env_get_u32("hal_h265e_debug", &hal_h265e_debug, 0); + hal_h265e_dbg_func("enter hal\n", hal); + + memset(ctx, 0, sizeof(HalH265eCtx)); + p_api = &ctx->hal_api; + + // NOTE: rk3036 and rk3228 do NOT have jpeg encoder + if (NULL == mpp_get_vcodec_dev_name(MPP_CTX_ENC, MPP_VIDEO_CodingHEVC)) { + mpp_err("SOC %s do NOT support h265 encoding\n", mpp_get_soc_name()); + ret = MPP_ERR_INIT; + goto FAIL; + } + + if (!(mpp_get_vcodec_type() & HAVE_H265ENC)) { + mpp_err("cannot find hardware.\n"); + ret = MPP_ERR_INIT; + goto FAIL; + } + p_api->init = hal_h265e_vepu22_init; + p_api->deinit = hal_h265e_vepu22_deinit; + p_api->reg_gen = hal_h265e_vepu22_gen_regs; + p_api->start = hal_h265e_vepu22_start; + p_api->wait = hal_h265e_vepu22_wait; + p_api->reset = hal_h265e_vepu22_reset; + p_api->flush = hal_h265e_vepu22_flush; + p_api->control = hal_h265e_vepu22_control; + + p_api->init(ctx, cfg); + + hal_h265e_dbg_func("leave hal %p\n", hal); + return MPP_OK; +FAIL: + return ret; +} + +MPP_RET hal_h265e_deinit(void *hal) +{ + HalH265eCtx* ctx = (HalH265eCtx*)hal; + return ctx->hal_api.deinit(hal); +} + +MPP_RET hal_h265e_gen_regs(void *hal, HalTaskInfo *task) +{ + HalH265eCtx* ctx = (HalH265eCtx*)hal; + return ctx->hal_api.reg_gen(hal, task); +} + +MPP_RET hal_h265e_start(void *hal, HalTaskInfo *task) +{ + HalH265eCtx* ctx = (HalH265eCtx*)hal; + return ctx->hal_api.start(hal, task); +} + +MPP_RET hal_h265e_wait(void *hal, HalTaskInfo *task) +{ + HalH265eCtx* ctx = (HalH265eCtx*)hal; + return ctx->hal_api.wait(hal, task); +} + +MPP_RET hal_h265e_reset(void *hal) +{ + HalH265eCtx* ctx = (HalH265eCtx*)hal; + return ctx->hal_api.reset(hal); +} + +MPP_RET hal_h265e_flush(void *hal) +{ + HalH265eCtx* ctx = (HalH265eCtx*)hal; + return ctx->hal_api.flush(hal); +} + +MPP_RET hal_h265e_control(void *hal, RK_S32 cmd_type, void *param) +{ + HalH265eCtx* ctx = (HalH265eCtx*)hal; + return ctx->hal_api.control(hal, cmd_type, param); +} + +const MppHalApi hal_api_h265e = { + "h265e_rkv", + MPP_CTX_ENC, + MPP_VIDEO_CodingHEVC, + sizeof(HalH265eCtx), + 0, + hal_h265e_init, + hal_h265e_deinit, + hal_h265e_gen_regs, + hal_h265e_start, + hal_h265e_wait, + hal_h265e_reset, + hal_h265e_flush, + hal_h265e_control, +}; + diff --git a/mpp/hal/rkenc/h265e/hal_h265e_base.h b/mpp/hal/rkenc/h265e/hal_h265e_base.h new file mode 100644 index 00000000..5b665e29 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_base.h @@ -0,0 +1,91 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HAL_H265E_BASE_H__ +#define __HAL_H265E_BASE_H__ + +#include "mpp_env.h" +#include "mpp_log.h" +#include "mpp_common.h" +#include "mpp_device.h" +#include "mpp_hal.h" + +extern RK_U32 hal_h265e_debug ; + +#define HAL_H265E_DBG_FUNCTION (0x00010000) +#define HAL_H265E_DBG_INPUT (0x00020000) +#define HAL_H265E_DBG_OUTPUT (0x00040000) +#define HAL_H265E_DBG_WRITE_IN_STREAM (0x00080000) +#define HAL_H265E_DBG_WRITE_OUT_STREAM (0x00100000) + +#define hal_h265e_dbg(flag, fmt, ...) _mpp_dbg(hal_h265e_debug, flag, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_f(flag, fmt, ...) _mpp_dbg_f(hal_h265e_debug, flag, fmt, ## __VA_ARGS__) + +#define hal_h265e_dbg_func(fmt, ...) hal_h265e_dbg_f(HAL_H265E_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_input(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_INPUT, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_output(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_OUTPUT, fmt, ## __VA_ARGS__) + + +typedef struct hal_h265e_ctx { + MppHalApi hal_api; + MppDevCtx dev_ctx; + MppBufferGroup buf_grp; + + /* + * the ion buffer's fd of ROI map + * ROI map holds importance levels for CTUs within a picture. The memory size is the number of CTUs of picture in bytes. + * For example, if there are 64 CTUs within a picture, the size of ROI map is 64 bytes. + * All CTUs have their ROI importance level (0 ~ 8 ; 1 byte) in raster order. + * A CTU with a high ROI important level is encoded with a lower QP for higher quality. + * It should be given when hw_cfg.ctu.roi_enable is 1. + */ + MppBuffer roi; + + /* + * Sthe ion buffer's fd of CTU qp map + * The memory size is the number of CTUs of picture in bytes. + * For example if there are 64 CTUs within a picture, the size of CTU map is 64 bytes. + * It should be given when hw_cfg.ctu.ctu_qp_enable is 1. + + * The content of ctuQpMap directly is mapped to the Qp used to encode the CTU. I.e, + * if (ctuQpMap[k]==5], it means that CTU(k) is encoded with Qp=5. + */ + MppBuffer ctu; + + void *en_info; + RK_U32 option; + RK_U32 user_cfg; + void *hw_cfg; + IOInterruptCB int_cb; + + + MppEncCfgSet *cfg; + MppEncCfgSet *set; + + RK_U32 init; + /* + * write yuv data(only for debug) + */ + FILE* mInFile; + + /* + * write bit stram data(only for debug) + */ + FILE* mOutFile; +} HalH265eCtx; + + +#endif diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu22.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu22.c new file mode 100644 index 00000000..e500ad0f --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu22.c @@ -0,0 +1,2009 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h265e_vepu22" + +#include + +#include "mpp_err.h" +#include "mpp_log.h" +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "h265e_syntax.h" +#include "hal_h265e_base.h" +#include "hal_h265e_vepu22_def.h" +#include "hal_h265e_vepu22.h" + + +#define H265E_MAX_ROI_LEVEL (8) +#define H265E_LOG2_CTB_SIZE (6) +#define H265E_CTB_SIZE (1 << H265E_LOG2_CTB_SIZE) +#define H265E_MAX_CTU_NUM 0x4000 // CTU num for max resolution = 8192x8192/(64x64) + +// this value must sync with kernel +#define MPP_H265E_BASE 0x1000 +#define H265E_SET_PARAMETER (MPP_H265E_BASE+6) +#define H265E_GET_HEADER (MPP_H265E_BASE+7) +#define H265E_RESET (MPP_H265E_BASE+8) + +typedef enum { + CODEOPT_ENC_HEADER_IMPLICIT = (1 << 0), /* A flag to encode (a) headers (VPS, SPS, PPS) implicitly for generating bitstreams conforming to spec. */ + CODEOPT_ENC_VCL = (1 << 1), /* A flag to encode VCL nal unit explicitly */ + CODEOPT_ENC_VPS = (1 << 2), /* A flag to encode VPS nal unit explicitly */ + CODEOPT_ENC_SPS = (1 << 3), /* A flag to encode SPS nal unit explicitly */ + CODEOPT_ENC_PPS = (1 << 4), /* A flag to encode PPS nal unit explicitly */ + CODEOPT_ENC_AUD = (1 << 5), /* A flag to encode AUD nal unit explicitly */ + CODEOPT_ENC_EOS = (1 << 6), /* A flag to encode EOS nal unit explicitly */ + CODEOPT_ENC_EOB = (1 << 7), /* A flag to encode EOB nal unit explicitly */ + CODEOPT_ENC_RESERVED = (1 << 8), /* reserved */ + CODEOPT_ENC_VUI = (1 << 9), /* A flag to encode VUI nal unit explicitly */ +} H265E_PIC_CODE_OPTION; + + +#if 0 +/* +* check mutli slice parameters +* h265 encoder support independ slice and depend slice. +* There are must independ slice when set multi slice,and independ_slice_mode must greater or equit than depend_slice_mode. +* There are only ctu mode(value = 1) in independ_slice_mode, and ctu mode(value = 1) and byte size(value = 2) +* in depend_slice_mode. +*/ +static MPP_RET vepu22_checkout_multi_slice(HalH265eCfg* cfg) +{ + if (cfg == NULL) { + mpp_err_f("error: param is null\n"); + return MPP_NOK; + } + + hal_h265e_dbg_func("enter\n"); + if (cfg->independ_slice_mode == 0 && cfg->depend_slice_mode != 0) { + mpp_err_f("error: independ_slice_mode = 0,depend_slice_mode must be 0\n"); + return -1; + } else if (cfg->independ_slice_mode == 1 && cfg->depend_slice_mode == 1) { + if (cfg->independ_slice_mode_arg < cfg->independ_slice_mode_arg) { + mpp_err_f("error: independ_slice_mode & depend_slice_mode is both" + " '1'(multi-slice with ctu count)," + " must be independ_slice_mode_arg >= independ_slice_mode_arg\n"); + return MPP_NOK; + } + } + + if (cfg->independ_slice_mode != 0) { + if (cfg->independ_slice_mode_arg > 65535) { + mpp_err_f("error: If independ_slice_mode is not 0, " + "must be independ_slice_mode_arg <= 0xFFFF\n"); + return MPP_NOK; + } + } + + if (cfg->depend_slice_mode != 0) { + if (cfg->independ_slice_mode_arg > 65535) { + mpp_err_f("error: If depend_slice_mode is not 0, " + "must be independ_slice_mode_arg <= 0xFFFF\n"); + return MPP_NOK; + } + } + + hal_h265e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET vepu22_check_ctu_parameter(HalH265eCtx* ctx) +{ + hal_h265e_dbg_func("enter\n"); + + HalH265eCfg* cfg = &ctx->hw_cfg; + // rc_enbale and ctu'qp can't both open + if (cfg->rc_enable && cfg->ctu.ctu_qp_enable) { + mpp_err_f("error: rc_mode and ctu qp enale can't both open,close ctu qp enable\n"); + cfg->ctu.ctu_qp_enable = 0; + } + + hal_h265e_dbg_func("leave\n"); + return MPP_OK; +} +#endif + +static RK_U8 vepu22_get_endian(int endian) +{ + switch (endian) { + case H265E_LITTLE_ENDIAN: + endian = 0x00; + break; + + case H265E_BIG_ENDIAN: + endian = 0x0f; + break; + + default: + mpp_err_f("error: endian = %d not support", endian); + return -1; + } + + return (endian & 0x0f); +} + +/* +* set vui parameter +* flags in struct vui every bit have meaning +*/ +static MPP_RET vepu22_set_default_vui_parameter(H265e_VUI* vui) +{ + if (vui == NULL) { + mpp_err_f("error: param is null\n"); + return MPP_NOK; + } + + hal_h265e_dbg_func("enter\n"); + + vui->flags = 0; + /* + * A flag whether to insertaspect_ratio_info_present_flag syntax of VUI parameters + * enable frame rate encode to vui + */ + vui->flags |= 1 << 3; + vui->aspect_ratio_idc = 0; + vui->sar_size = 0; + vui->over_scan_appropriate = 0; + + vui->signal = 0; + vui->chroma_sample_loc = 0; + vui->disp_win_left_right = 0; + vui->disp_win_top_bottom = 0; + + hal_h265e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET vepu22_set_rc_default_parameter(HalH265eCfg* cfg) +{ + hal_h265e_dbg_func("enter\n"); + + cfg->min_qp = 8; + cfg->max_qp = 51; + cfg->max_delta_qp = 10; + cfg->initial_rc_qp = 63; + cfg->init_buf_levelx8 = 1; + cfg->intra_qp_offset = 0; + cfg->hvs_qp_enable = 0;// 1; + cfg->cu_level_rc_enable = 1; + cfg->trans_rate = 0; + cfg->initial_delay = 100; + + // close rc enable default + cfg->rc_enable = 0; + + hal_h265e_dbg_func("leave\n"); + return MPP_OK; +} + +/* +* set h265 encoder default parameters +*/ +static MPP_RET vepu22_set_default_hw_cfg(HalH265eCfg* cfg) +{ + RK_U32 i = 0; + + hal_h265e_dbg_func("enter\n"); + + cfg->cfg_option = H265E_OPT_ALL_PARAM; + cfg->cfg_mask = H265E_CFG_CHANGE_SET_PARAM_ALL; + // support profile main ,level 4.1 + cfg->profile = H265E_Profile_Main; + cfg->level = H265E_MAIN_LEVEL41; + cfg->tier = H265E_MAIN_TILER; + + // only YUV_420 8bit + cfg->chroma_idc = 0; + cfg->lossless_enable = 0; + cfg->const_intra_pred_flag = 0; + + cfg->chroma_cb_qp_offset = 0; + cfg->chroma_cr_qp_offset = 0; + + cfg->width = 0; + cfg->height = 0; + cfg->bit_depth = 8; + cfg->src_format = H265E_SRC_YUV_420; + cfg->frame_rate = 30; + cfg->frame_skip = 0; + + cfg->src_endian = vepu22_get_endian(H265E_BIG_ENDIAN); + cfg->bs_endian = vepu22_get_endian(H265E_BIG_ENDIAN); + // only support value 0,detail see register SFB_OPTION (0x0000010C) + cfg->fb_endian = vepu22_get_endian(H265E_LITTLE_ENDIAN); + + cfg->codeOption.implicitHeaderEncode = 1; + cfg->codeOption.encodeVCL = 1; + cfg->codeOption.encodeVPS = 1; + cfg->codeOption.encodeSPS = 1; + cfg->codeOption.encodePPS = 1; + // fbc may type: only support COMPRESSED_FRAME_MAP + cfg->fbc_map_type = COMPRESSED_FRAME_MAP; + + cfg->use_cur_as_longterm_pic = 0; + cfg->use_longterm_ref = 0; + cfg->use_long_term = 0; + + /* for CMD_ENC_SEQ_INTRA_PARAM */ + cfg->decoding_refresh_type = 1; + cfg->intra_period = 32; + cfg->intra_qp = 26; + + /* for CMD_ENC_SEQ_CONF_WIN_TOP_BOT/LEFT_RIGHT */ + cfg->conf_win_top = 0; + cfg->conf_win_bot = 0; + cfg->conf_win_left = 0; + cfg->conf_win_right = 0; + + /* for CMD_ENC_SEQ_INDEPENDENT_SLICE */ + cfg->independ_slice_mode = 0; + cfg->independ_slice_mode_arg = 0; + + /* for CMD_ENC_SEQ_DEPENDENT_SLICE */ + cfg->depend_slice_mode = 0; + cfg->depend_slice_mode_arg = 0; + + /* for CMD_ENC_SEQ_INTRA_REFRESH_PARAM */ + cfg->intra_in_inter_slice_enable = 0; + cfg->intra_refresh_mode = 0; + cfg->intra_refresh_arg = 0; + cfg->use_recommend_param = 0;// 1; + + cfg->sei.prefix_sei_nal_enable = 0; + cfg->sei.suffix_sei_nal_enable = 0; + + cfg->hrd_rbsp_in_vps = 0; + cfg->hrd_rbsp_in_vui = 0; + cfg->vui_rbsp = 0; + + /* for CMD_ENC_PARAM */ + if (cfg->use_recommend_param == 0) { + cfg->scaling_list_enable = 0; // ScalingList + cfg->cu_size_mode = 0x07; // enable CU8x8, CU16x16, CU32x32 + cfg->tmvp_enable = 1; // EnTemporalMVP + cfg->wpp_enable = 0; + cfg->max_num_merge = 2; + cfg->dynamic_merge_8x8_enable = 1; + cfg->dynamic_merge_16x16_enable = 1; + cfg->dynamic_merge_32x32_enable = 1; + cfg->disable_deblk = 0; + cfg->lf_cross_slice_boundary_enable = 1; + cfg->beta_offset_div2 = 0; + cfg->tc_offset_div2 = 0; + cfg->skip_intra_trans = 0; + cfg->sao_enable = 1; + cfg->intra_qp_offset = 1; + cfg->intra_nxn_enable = 0; + } + + /* for CMD_ENC_RC_PARAM */ + cfg->ctu.roi_enable = 0; + cfg->ctu.roi_delta_qp = 3; + cfg->ctu.map_endian = 0; + cfg->intra_qp_offset = 0; + cfg->bit_alloc_mode = 0; + + for (i = 0; i < H265E_MAX_GOP_NUM; i++) { + cfg->fixed_bit_ratio[i] = 1; + } + + cfg->hvs_qp_enable = 0;// 1; + cfg->hvs_qp_scale_enable = 0; + cfg->hvs_qp_scale = 0; + + /* for CMD_ENC_CUSTOM_GOP_PARAM */ + cfg->gop_idx = PRESET_IDX_CUSTOM_GOP; + cfg->gop.custom_gop_size = 8; // 1~8 + cfg->gop.use_derive_lambda_weight = 1; // DeriveLambdaWeight + if (cfg->intra_period == 1) { + cfg->gop_idx = PRESET_IDX_ALL_I; + } else { + cfg->gop_idx = PRESET_IDX_CUSTOM_GOP; + } + + if (cfg->gop_idx == PRESET_IDX_CUSTOM_GOP) { + for (i = 0; i < cfg->gop.custom_gop_size; i++) { + if (i == 0) { + cfg->gop.pic[i].ref_poc_l0 = 0; + } else { + cfg->gop.pic[i].ref_poc_l0 = i - 1; + } + cfg->gop.pic[i].type = H265E_PIC_TYPE_P; + //not set pocOffset to 0,because the first I frame's will be take the pocOffset 0 + cfg->gop.pic[i].offset = i + 1; + cfg->gop.pic[i].qp = cfg->intra_qp; + cfg->gop.pic[i].ref_poc_l1 = 0; + cfg->gop.pic[i].temporal_id = 0; + cfg->gop.gop_pic_lambda[i] = 0; + } + } + + // for VUI / time information. + cfg->num_ticks_poc_diff_one = 0; + cfg->time_scale = cfg->frame_rate * 1000; + cfg->num_units_in_tick = 1000; + + cfg->vui.flags = 0; // when vuiParamFlags == 0, VPU doesn't encode VUI + + cfg->nr_y_enable = 0; + cfg->nr_cb_enable = 0; + cfg->nr_cr_enable = 0; + cfg->nr_noise_est_enable = 1; + cfg->nr_intra_weight_y = 7; + cfg->nr_intra_weight_cb = 7; + cfg->nr_intra_weight_cr = 7; + cfg->nr_inter_weight_y = 4; + cfg->nr_inter_weight_cb = 4; + cfg->nr_inter_weight_cr = 4; + + cfg->intra_min_qp = 8; + cfg->intra_max_qp = 51; + + vepu22_set_default_vui_parameter(&cfg->vui); + vepu22_set_rc_default_parameter(cfg); + + hal_h265e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET vepu22_clear_cfg_mask(HalH265eCtx* cfg) +{ + HalH265eCfg *hw_cfg = (HalH265eCfg *)cfg->hw_cfg; + + hw_cfg->cfg_mask = 0; + hw_cfg->cfg_option = 0; + + return MPP_OK; +} + +/* +* check prep parameter is valid +*/ +static MPP_RET vepu22_check_prep_parameter(MppEncPrepCfg *set) +{ + if (set == NULL) { + mpp_err_f("parameter is NULL\n"); + return MPP_NOK; + } + + if (set->width < 256 && set->width > 1920) { + mpp_err_f("ERROR: invalid width %d is not in range [256..1920]\n", set->width); + return MPP_NOK; + } + + if (set->height < 128 && set->height > 1080) { + mpp_err_f("ERROR: invalid height %d is not in range [128..1080]\n", set->height); + return MPP_NOK; + } + + if (set->hor_stride < set->width) { + mpp_err_f("WARNING: hor_stride(%d) < cfg->width(%d),force hor_stride = width\n", + set->hor_stride, set->width); + set->hor_stride = set->width; + } + + if (set->ver_stride < set->height) { + mpp_err_f("WARNING: ver_stride(%d) < cfg->height(%d),force ver_stride = height\n", + set->ver_stride, set->height); + set->ver_stride = set->height; + } + + if (set->format != MPP_FMT_YUV420SP && + set->format != MPP_FMT_YUV420P && + set->format != MPP_FMT_YUV420SP_VU) { + mpp_err_f("ERROR: invalid format %d is not supportted\n", set->format); + return MPP_NOK; + } + + return MPP_OK; +} + +static MPP_RET vepu22_force_frame_type(H265E_PIC_TYPE type, EncInfo* info) +{ + if (info == NULL) { + mpp_err_f("error: info = %p\n", info); + return MPP_NOK; + } + + if (type < H265E_PIC_TYPE_I || + type > H265E_PIC_TYPE_CRA || + type == H265E_PIC_TYPE_B) { + mpp_err_f("error: type = %d not support\n"); + return MPP_NOK; + } + + info->force_frame_type_enable = 1; + info->force_frame_type = type; + + return MPP_OK; +} + + +static MPP_RET vepu22_set_frame_type(H265eSyntax *syntax, EncInfo* info) +{ + if (syntax == NULL || info == NULL) { + mpp_err_f("error: syntax = %p,info = %p\n", syntax, info); + return MPP_NOK; + } + if (syntax->idr_request > 0) { + vepu22_force_frame_type(H265E_PIC_TYPE_IDR, info); + syntax->idr_request --; + } else { + info->force_frame_type_enable = 0; + info->force_frame_type = 0; + } + + return MPP_OK; +} + +static MPP_RET vepu22_set_ctu_qp(HalH265eCtx* ctx) +{ + EncInfo *en_info = (EncInfo *)ctx->en_info; + HalH265eCfg* hw_cfg = (HalH265eCfg *)ctx->hw_cfg; + + en_info->ctu_qp_fd = 0; + if (ctx->ctu != NULL && hw_cfg->ctu.ctu_qp_enable > 0) { + en_info->ctu_qp_fd = mpp_buffer_get_fd(ctx->ctu); + } + return MPP_OK; +} + +static MPP_RET vepu22_set_roi_region(HalH265eCtx *ctx) +{ + EncInfo *en_info = (EncInfo *)ctx->en_info; + HalH265eCfg *hw_cfg = (HalH265eCfg *)ctx->hw_cfg; + + en_info->roi_fd = 0; + if (ctx->roi != NULL && hw_cfg->ctu.roi_enable > 0) { + en_info->roi_fd = mpp_buffer_get_fd(ctx->roi); + } + return MPP_OK; +} + +static RK_S32 vepu22_get_yuv_format(RK_S32 format) +{ + switch (format) { + case MPP_FMT_YUV420SP: + return H265E_SRC_YUV_420_NV12; + + case MPP_FMT_YUV420P: + return H265E_SRC_YUV_420_YU12; + + case MPP_FMT_YUV420SP_VU: + return H265E_SRC_YUV_420_NV21; + + default: + return H265E_SRC_YUV_420_YV12; + } + + return H265E_SRC_YUV_420_YV12; +} + +static MPP_RET vepu22_check_roi_parameter(void *cfg) +{ + MppEncH265RoiCfg* roi = (MppEncH265RoiCfg*)cfg; + + if (roi->num) { + if (roi->delta_qp < 1 || roi->delta_qp > 51) { + mpp_err_f("error: syntax->roi.delta_qp = %d must between [1,51]\n", roi->delta_qp); + return MPP_NOK; + } + } + + return MPP_OK; +} + +/* + * set ROI's map + * user can set some ROI regions, the ROI regions will have small + * qp value when encode.The ROI regions use ctu size as a unit. + * ROI's map is a buffer cotain define roi's level. The buffer index is + * the coordinates with CTU as the unit. For example: + * there are two roi' region, the value of level are 1 and 2, + * this function first convert the region's pixel coordinates to + * CTU coordinates, and set those ctu's level value. + ***************************************************************** + * * * * * * * * * * * * * 2 * 2 * 2 * 2 * + ***************************************************************** + * * * * *1 *1 *1 *1 *1 * * * * 2 * 2 * 2 * 2 * + ***************************************************************** + * * * * *1 *1 *1 *1 *1 * * * * 2 * 2 * 2 * 2 * + ***************************************************************** + * * * * *1 *1 *1 *1 *1 * * * * * * * * + ***************************************************************** + * * * * * * * * * * * * * * * * * + ***************************************************************** + * + * NOTE: ROI enable only work when Rate Control is enable + */ +static MPP_RET vepu22_set_roi_region_parameter(HalH265eCtx* ctx, void *para) +{ + H265e_CTU *ctu = NULL; + MppEncH265RoiCfg *roi = (MppEncH265RoiCfg*)para; + MppEncH265RoiCfg local_roi; + H265eRoiRegion *region = NULL; + H265eRoiRegion *region1 = NULL; + H265eRect* rect = NULL; + RK_S32 i = 0; + RK_S32 x = 0, y = 0; + RK_S32 left = 0, right = 0; + RK_S32 top = 0, bottom = 0; + RK_S32 width, height; + RK_S32 map_width;//, map_height; + RK_S32 roi_number = 0; + RK_S32 roi_id = 0; + RK_U8 *region_buf = NULL; + MPP_RET ret = MPP_OK; + HalH265eCfg *hw_cfg = NULL; + + hal_h265e_dbg_func("enter\n"); + if (ctx == NULL || roi == NULL) { + mpp_err_f("error: parameter is invalid"); + return MPP_NOK; + } + + hw_cfg = (HalH265eCfg *)ctx->hw_cfg; + hal_h265e_dbg_func("cfg_mask = 0x%x\n", hw_cfg->cfg_mask); + if (vepu22_check_roi_parameter(roi) != MPP_OK) { + return MPP_OK; + } + + width = hw_cfg->width; + height = hw_cfg->height; + ctu = &hw_cfg->ctu; + map_width = MPP_ALIGN(width, 64) >> 6; +// map_height = MPP_ALIGN(height, 64) >> 6; + memset(&local_roi, 0, sizeof(MppEncH265RoiCfg)); + + + for (i = 0; i < roi->num; i++) { + // check ROI's Level + region = &roi->region[i]; + if (region->level > H265E_MAX_ROI_LEVEL) { + return MPP_NOK; + } + + // check ROI's region, the ROI's region is used CTU as a Unit. + rect = &(region->rect); + if (rect->left < 0 || rect->top < 0) { + return MPP_NOK; + } + + if (rect->left > rect->right) { + return MPP_NOK; + } + + if (rect->top > rect->bottom) { + return MPP_NOK; + } + + if ((rect->left >= width) || (rect->top >= height)) { + mpp_err("rect->left = %d,rect->top = %d\n", rect->left, rect->top); + mpp_err("rect->left must less than %d,rect->top must less than %d\n", width, height); + return MPP_NOK; + } + hal_h265e_dbg_input("rect->method = %d\n", roi->method); + if (roi->method == H264E_METHOD_COORDINATE) { + if ((rect->right > (width + H265E_CTB_SIZE - 1)) || + (rect->bottom > (height + H265E_CTB_SIZE - 1))) { + mpp_err("rect->right = %d,rect->top = %d\n", rect->right, rect->bottom); + mpp_err("rect->right must less than %d,rect->bottom must less than %d\n", + (width + H265E_CTB_SIZE - 1), (height + H265E_CTB_SIZE - 1)); + return MPP_NOK; + } + + // covert to unit of ctu + hal_h265e_dbg_input("rect->left = %d,rect->right = %d,rect->top = %d,rect->bottom = %d\n", + rect->left, rect->right, rect->top, rect->bottom); + left = (RK_S32)((rect->left + H265E_CTB_SIZE - 1) >> H265E_LOG2_CTB_SIZE); + right = (RK_S32)((rect->right + H265E_CTB_SIZE - 1) >> H265E_LOG2_CTB_SIZE); + top = (RK_S32)((rect->top + H265E_CTB_SIZE - 1) >> H265E_LOG2_CTB_SIZE); + bottom = (RK_S32)((rect->bottom + H265E_CTB_SIZE - 1) >> H265E_LOG2_CTB_SIZE); + } else { + left = rect->left; + right = rect->right; + top = rect->top; + bottom = rect->bottom; + } + region1 = &local_roi.region[roi_number]; + region1->level = region->level; + region1->rect.left = left; + region1->rect.right = right; + region1->rect.top = top; + region1->rect.bottom = bottom; + + roi_number ++; + } + + if (roi_number > 0) { + if (ctx->roi == NULL) { + ret = mpp_buffer_get(ctx->buf_grp, &ctx->roi, H265E_MAX_CTU_NUM); + if (ctx->roi == NULL) { + mpp_err("failed to get buffer for roi buffer ret %d\n", ret); + return MPP_NOK; + } + } + + region_buf = mpp_buffer_get_ptr(ctx->roi); + memset(region_buf, 0, H265E_MAX_CTU_NUM); + + //set roi map. roi_entry[i] has higher priority than roi_entry[i+1] + + hal_h265e_dbg_func("roi_number = %d\n", roi_number); + for (roi_id = (roi_number - 1); roi_id >= 0; roi_id--) { + region1 = &local_roi.region[roi_id]; + rect = ®ion1->rect; + for (y = rect->top; y <= rect->bottom; y++) { + for (x = rect->left; x <= rect->right; x++) { + /* + * every roi_entry[i] mean a ctu, if a ctu belong to a roi, + * then set roi's level to buffer + */ + region_buf[y * map_width + x] = (RK_U8)region1->level; + } + } + } + + ctu->roi_enable = 1; + ctu->map_endian = vepu22_get_endian(H265E_BIG_ENDIAN); + ctu->map_stride = map_width; + ctu->roi_delta_qp = roi->delta_qp; + + if (hw_cfg->hvs_qp_enable == 1) { + hw_cfg->hvs_qp_enable = 0; + hal_h265e_dbg_func("roi_enable and hvs_qp_enable can't both 1,close hvs_qp_enable"); + } + + } else { + ctu->roi_enable = 0; + } + + hw_cfg->cfg_mask |= H265E_CFG_RC_PARAM_CHANGE; + hw_cfg->cfg_option |= H265E_PARAM_CHANEGED_COMMON; + + hal_h265e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET vepu22_set_roi(HalH265eCtx* ctx, void *param) +{ + MppEncH265RoiCfg *roi = (MppEncH265RoiCfg*)param; + HalH265eCfg *hw_cfg = (HalH265eCfg *)ctx->hw_cfg; + /* + * if already init, do not change value of roi_enable. + * ctu_qp_enable only can be set before encoder init. + * if encoder already init, can only change the ctu's region and qp value + */ + if (ctx->init == 1) { + if (roi->num == 0 && hw_cfg->ctu.roi_enable == 1) { + return MPP_NOK; + } else if (roi->num == 1 && hw_cfg->ctu.roi_enable == 0) { + return MPP_NOK; + } + + return vepu22_set_roi_region_parameter(ctx, param); + } else { + return vepu22_set_roi_region_parameter(ctx, param); + } +} + +/* + * set ctu's qp map + * user can set some regions's qp, the regions use ctu size as a unit + * ctu map is a buffer cotain define qp value. The buffer index is + * the coordinates with CTU as the unit. For example: + * there are two ctu' region, the value of qp are 51 and 10, + * this function first convert the region's pixel coordinates to + * CTU coordinates, and set those ctu's qp value. + ***************************************************************** + * * * * * * * * * * * * * 51* 51* 51* 51* + ***************************************************************** + * * * * *10 *10 *10 *10 *10 * * * * 51* 51* 51* 51* + ***************************************************************** + * * * * *10 *10 *10 *10 *10 * * * * 51* 51* 51* 51* + ***************************************************************** + * * * * *10 *10 *10 *10 *10 * * * * * * * * + ***************************************************************** + * * * * * * * * * * * * * * * * * + ***************************************************************** + * + * NOTE: ctu qp enable can't set when Rate Control is disable + */ +static MPP_RET vepu22_set_ctu_parameter(HalH265eCtx* ctx, void *param) +{ + MppEncH265CtuCfg *ctu_region = (MppEncH265CtuCfg*)param; + H265e_CTU *ctu_cfg = NULL; + H265eRect* rect = NULL; + RK_S32 i = 0; + RK_S32 x = 0, y = 0; + RK_S32 width, height; + RK_S32 map_width;//, map_height; + RK_U8 *ctu_qp_buf = NULL; + H265eCtu* ctu = NULL; + MPP_RET ret = MPP_OK; + RK_S32 valid = 0; + RK_S32 left = 0, right = 0; + RK_S32 top = 0, bottom = 0; + HalH265eCfg *hw_cfg = NULL; + + hal_h265e_dbg_func("enter\n"); + if (ctx == NULL || param == NULL) { + mpp_err_f("error: parameter is invalid"); + return MPP_NOK; + } + + if (ctx->ctu == NULL) { + ret = mpp_buffer_get(ctx->buf_grp, &ctx->ctu, H265E_MAX_CTU_NUM); + if (ctx->ctu == NULL) { + mpp_err("failed to get buffer for roi buffer ret %d\n", ret); + return MPP_NOK; + } + } + hw_cfg = (HalH265eCfg *)ctx->hw_cfg; + + ctu_qp_buf = mpp_buffer_get_ptr(ctx->ctu); + if (ctu_qp_buf == NULL) { + mpp_err_f("error: ctu_qp_buf is NULL"); + return MPP_NOK; + } + + memset(ctu_qp_buf, hw_cfg->intra_qp, H265E_MAX_CTU_NUM); + + width = hw_cfg->width; + height = hw_cfg->height; + map_width = MPP_ALIGN(width, 64) >> 6; + ctu_cfg = &hw_cfg->ctu; +// map_height = MPP_ALIGN(height, 64) >> 6; + + for (i = 0; i < ctu_region->num; i++) { + // check ROI's region, the ROI's region is used CTU as a Unit. + ctu = &(ctu_region->ctu[i]); + rect = &(ctu->rect); + if (rect->left < 0 || rect->top < 0) { + return MPP_NOK; + } + + if (rect->left > rect->right) { + return MPP_NOK; + } + + if (rect->top > rect->bottom) { + return MPP_NOK; + } + + if ((rect->left >= width) || (rect->top >= height)) { + mpp_err_f("rect->left = %d,rect->top = %d\n", rect->left, rect->top); + mpp_err_f("rect->left must less than %d,rect->top must less than %d\n", + width, height); + return MPP_NOK; + } + + + if (ctu_region->method == H264E_METHOD_COORDINATE) { + if ((rect->right > (width + H265E_CTB_SIZE - 1)) || + (rect->bottom > (height + H265E_CTB_SIZE - 1))) { + mpp_err_f("rect->right = %d,rect->top = %d\n", rect->right, rect->bottom); + mpp_err_f("rect->right must less than %d,rect->bottom must less than %d\n", + (width + H265E_CTB_SIZE - 1), (height + H265E_CTB_SIZE - 1)); + return MPP_NOK; + } + + /* + * if method = H264E_METHOD_COORDINATE,then the value of rect is + * in coordinates unit, so we must translate the values to ctu size + */ + left = (RK_S32)((rect->left + H265E_CTB_SIZE - 1) >> H265E_LOG2_CTB_SIZE); + right = (RK_S32)((rect->right + H265E_CTB_SIZE - 1) >> H265E_LOG2_CTB_SIZE); + top = (RK_S32)((rect->top + H265E_CTB_SIZE - 1) >> H265E_LOG2_CTB_SIZE); + bottom = (RK_S32)((rect->bottom + H265E_CTB_SIZE - 1) >> H265E_LOG2_CTB_SIZE); + } else { + left = rect->left; + right = rect->right; + top = rect->top; + bottom = rect->bottom; + } + + for (y = top; y <= bottom; y++) { + for (x = left; x <= right; x++) { + ctu_qp_buf[y * map_width + x] = ctu->qp; + valid = 1; + } + } + } + + if (valid > 0) { + ctu_cfg->ctu_qp_enable = 1; + ctu_cfg->map_endian = vepu22_get_endian(H265E_BIG_ENDIAN); + ctu_cfg->map_stride = map_width; + hal_h265e_dbg_func("ctu_cfg->ctu_qp_enable = 1\n"); + } else { + ctu_cfg->ctu_qp_enable = 0; + } + + hw_cfg->cfg_mask |= H265E_CFG_PARAM_CHANGE; + hw_cfg->cfg_option |= H265E_PARAM_CHANEGED_COMMON; + + hal_h265e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET vepu22_set_ctu(HalH265eCtx* ctx, void *param) +{ + MppEncH265CtuCfg *ctu = (MppEncH265CtuCfg*)param; + HalH265eCfg *hw_cfg = (HalH265eCfg *)ctx->hw_cfg; + /* + * if already init, do not change value of ctu_qp_enable. + * ctu_qp_enable only can be set before encoder init. + * if encoder already init, can only change the ctu's region and qp value + */ + if (ctx->init == 1) { + if (ctu->num == 0 && hw_cfg->ctu.ctu_qp_enable == 1) { + return MPP_NOK; + } else if (ctu->num == 1 && hw_cfg->ctu.ctu_qp_enable == 0) { + return MPP_NOK; + } + + return vepu22_set_ctu_parameter(ctx, param); + } else { + return vepu22_set_ctu_parameter(ctx, param); + } +} + +static MPP_RET vepu22_check_rc_parameter(HalH265eCtx *ctx) +{ + hal_h265e_dbg_func("enter\n"); + + HalH265eCfg *hw_cfg = (HalH265eCfg *)ctx->hw_cfg; + + if (hw_cfg->min_qp < 0 || hw_cfg->min_qp > 51) { + mpp_err_f("error: hw_cfg->min_qp = %d is invalid", hw_cfg->min_qp); + return MPP_NOK; + } + + if (hw_cfg->max_qp < 0 || hw_cfg->max_qp > 51) { + mpp_err_f("error: hw_cfg->max_qp = %d is invalid", hw_cfg->max_qp); + return MPP_NOK; + } + + if (hw_cfg->initial_rc_qp < 0 || hw_cfg->initial_rc_qp > 63) { + mpp_err_f("error: syntax->inital_rc_qp = %d is invalid\n", + hw_cfg->initial_rc_qp); + return MPP_NOK; + } + + if ((hw_cfg->initial_rc_qp < 52) && + ((hw_cfg->initial_rc_qp > hw_cfg->max_qp) || + (hw_cfg->initial_rc_qp < hw_cfg->min_qp))) { + mpp_err_f("error: nital_rc_qp < 52 must between min_qp = %d...max_qp = %d\n", + hw_cfg->min_qp, hw_cfg->max_qp); + return MPP_NOK; + } + + if (hw_cfg->intra_qp_offset < -10 || hw_cfg->intra_qp_offset > 10) { + mpp_err_f("error: intra_qp_offset = %d must between [-10,10]", + hw_cfg->intra_qp_offset); + return MPP_NOK; + } + + if (hw_cfg->cu_level_rc_enable != 1 && hw_cfg->cu_level_rc_enable != 0) { + mpp_err_f("error: cu_level_rc_enable = %d is invalid", + hw_cfg->cu_level_rc_enable); + return MPP_NOK; + } + + if (hw_cfg->init_buf_levelx8 == 1) { + if (hw_cfg->hvs_qp_enable != 1 && hw_cfg->hvs_qp_enable != 0) { + mpp_err_f("error: syntax->hvs_qp_enable = %d is invalid", + hw_cfg->hvs_qp_enable); + return MPP_NOK; + } + + if (hw_cfg->hvs_qp_enable) { + if (hw_cfg->max_delta_qp < 0 || hw_cfg->max_delta_qp > 51) { + mpp_err_f("error: syntax->max_delta_qp = %d is invalid", + hw_cfg->max_delta_qp); + return MPP_NOK; + } + + if (hw_cfg->hvs_qp_scale_enable != 1 && hw_cfg->hvs_qp_scale_enable != 0) { + mpp_err_f("error: syntax->hvs_qp_scale_enable = %d is invalid", + hw_cfg->hvs_qp_scale_enable); + return MPP_NOK; + } + + if (hw_cfg->hvs_qp_scale_enable == 1) { + if (hw_cfg->hvs_qp_scale < 0 || hw_cfg->hvs_qp_scale > 4) { + mpp_err_f("error: syntax->hvs_qp_scale = %d is invalid", + hw_cfg->hvs_qp_scale); + return MPP_NOK; + } + } + } + } + + // if (syntax->bit_alloc_mode < 0 && param->bit_alloc_mode > 2) + // return RETCODE_INVALID_PARAM; + + if (hw_cfg->init_buf_levelx8 < 0 || hw_cfg->init_buf_levelx8 > 8) { + mpp_err_f("error: syntax->init_buf_level = %d must between [0,8]", + hw_cfg->init_buf_levelx8); + return MPP_NOK; + } + + if (hw_cfg->initial_delay < 10 || hw_cfg->initial_delay > 3000 ) { + mpp_err_f("error: syntax->inital_delay = %d must between [10,3000]", + hw_cfg->initial_delay); + return MPP_NOK; + } + + if (hw_cfg->ctu.roi_enable && hw_cfg->rc_enable == 0) { + mpp_err_f("error: roi_enable = 1 must when rc_enable = 1,close roi_enable"); + hw_cfg->ctu.roi_enable = 0; + } + + if (hw_cfg->ctu.roi_enable && hw_cfg->rc_enable && hw_cfg->hvs_qp_enable > 1) { + // can not use both ROI and hvsQp + mpp_err_f("error: roi and hvs_qp_enable can't use both,close roi_enable"); + hw_cfg->ctu.roi_enable = 0; + } + + hal_h265e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET vepu22_check_encode_parameter(HalH265eCtx* ctx) +{ + RK_S32 intra_period_gop_step_size = 0; + RK_U32 i = 0; + RK_S32 low_delay = 0; + MPP_RET ret = MPP_OK; + + HalH265eCfg *hw_cfg = (HalH265eCfg *)ctx->hw_cfg; + hal_h265e_dbg_func("in\n"); + + hal_h265e_dbg_func("cfg = %p,cfg->gop_idx = %d\n", hw_cfg, hw_cfg->gop_idx); + static uint32_t presetGopSize[] = { + 1, /* Custom GOP, Not used */ + 1, /* All Intra */ + 1, /* IPP Cyclic GOP size 1 */ + 1, /* IBB Cyclic GOP size 1 (not support)*/ + 2, /* IBP Cyclic GOP size 2 */ + 4, /* IBBBP (not support)*/ + 4, + 4, + 8, + }; + hal_h265e_dbg_func("hw_cfg->gop_idx = %d\n", hw_cfg->gop_idx); + // check low-delay gop structure + if (hw_cfg->gop_idx == PRESET_IDX_CUSTOM_GOP) { // common gop + RK_U32 min_offset = 0; + if (hw_cfg->gop.custom_gop_size > 1) { + min_offset = hw_cfg->gop.pic[0].offset; + low_delay = 1; + for (i = 1; i < hw_cfg->gop.custom_gop_size; i++) { + if (min_offset > hw_cfg->gop.pic[i].offset) { + low_delay = 0; + break; + } else { + min_offset = hw_cfg->gop.pic[i].offset; + } + } + } + } else if (hw_cfg->gop_idx == PRESET_IDX_IPP || + hw_cfg->gop_idx == PRESET_IDX_IPPPP) { + // low-delay case + low_delay = 1; + } + hal_h265e_dbg_func("low_delay = %d,hw_cfg->gop_idx = %d\n", + low_delay, hw_cfg->gop_idx); + if (low_delay) { + intra_period_gop_step_size = 1; + } else { + if (hw_cfg->gop_idx == PRESET_IDX_CUSTOM_GOP) { + intra_period_gop_step_size = hw_cfg->gop.custom_gop_size ; + hal_h265e_dbg_func("PRESET_IDX_CUSTOM_GOP,intra_period_gop_step_size = %d\n", + intra_period_gop_step_size); + } else { + intra_period_gop_step_size = presetGopSize[hw_cfg->gop_idx]; + hal_h265e_dbg_func("presetGopSize[%d],intra_period_gop_step_size = %d\n", + hw_cfg->gop_idx, intra_period_gop_step_size); + } + } + hal_h265e_dbg_func("intra_period = %d,intra_period_gop_step_size = %d\n", + hw_cfg->intra_period, intra_period_gop_step_size); + hal_h265e_dbg_func("decoding_refresh_type = %d", + hw_cfg->decoding_refresh_type); + if (!low_delay && + (hw_cfg->intra_period != 0) && + ((hw_cfg->intra_period % intra_period_gop_step_size) != 0) + && (hw_cfg->decoding_refresh_type != 0)) { + mpp_err_f("CFG FAIL : Not support intra period[%d] for the gop structure\n", + hw_cfg->intra_period); + mpp_err_f("RECOMMEND CONFIG PARAMETER : Intra period = %d\n", + intra_period_gop_step_size * (hw_cfg->intra_period / intra_period_gop_step_size)); + return MPP_NOK; + } + + if (!low_delay && (hw_cfg->intra_period != 0) && + ((hw_cfg->intra_period % intra_period_gop_step_size) == 1) && + (hw_cfg->decoding_refresh_type == 0)) { + mpp_err_f("CFG FAIL : Not support decoding refresh type[%d] for closed gop structure\n", + hw_cfg->decoding_refresh_type); + mpp_err_f("RECOMMEND CONFIG PARAMETER : Decoding refresh type = IDR\n"); + return MPP_NOK; + } + + if (hw_cfg->gop_idx == PRESET_IDX_CUSTOM_GOP) { + for (i = 0; i < hw_cfg->gop.custom_gop_size; i++) { + if (hw_cfg->gop.pic[i].temporal_id >= H265E_MAX_NUM_TEMPORAL_LAYER) { + mpp_err_f("CFG FAIL : temporalId %d exceeds MAX_NUM_TEMPORAL_LAYER\n", \ + hw_cfg->gop.pic[i].temporal_id); + mpp_err_f("RECOMMEND CONFIG PARAMETER :" + "Adjust temporal ID under MAX_NUM_TEMPORAL_LAYER(7) in GOP structure\n"); + return MPP_NOK; + } + } + } + + if (hw_cfg->use_recommend_param == 0) { + // Intra + if (hw_cfg->intra_in_inter_slice_enable == 0 && hw_cfg->intra_refresh_mode != 0) { + mpp_err_f("CFG FAIL : If intraInInterSliceEnable is '0'," + "Intra refresh mode must be '0'\n"); + mpp_err_f("RECOMMEND CONFIG PARAMETER : intraRefreshMode = 0\n"); + return MPP_NOK; + } + + // RDO + { + int align_32_width_flag = hw_cfg->width % 32; + int align_16_width_flag = hw_cfg->width % 16; + int align_8_width_flag = hw_cfg->width % 8; + int align_32_height_flag = hw_cfg->height % 32; + int align_16_height_flag = hw_cfg->height % 16; + int align_8_height_flag = hw_cfg->height % 8; + + if ( ((hw_cfg->cu_size_mode & 0x1) == 0) && ((align_8_width_flag != 0) || (align_8_height_flag != 0)) ) { + mpp_err_f("CFG FAIL : Picture width and height must be aligned with 8 pixels when enable CU8x8 of cuSizeMode \n"); + mpp_err_f("RECOMMEND CONFIG PARAMETER : cuSizeMode |= 0x1 (CU8x8)\n"); + return MPP_NOK; + } else if (((hw_cfg->cu_size_mode & 0x1) == 0) && ((hw_cfg->cu_size_mode & 0x2) == 0) && + ((align_16_width_flag != 0) || (align_16_height_flag != 0)) ) { + mpp_err_f("CFG FAIL : Picture width and height must be aligned with 16 pixels when enable CU16x16 of cuSizeMode\n"); + mpp_err_f("RECOMMEND CONFIG PARAMETER : cuSizeMode |= 0x2 (CU16x16)\n"); + return MPP_NOK; + } else if (((hw_cfg->cu_size_mode & 0x1) == 0) && ((hw_cfg->cu_size_mode & 0x2) == 0) + && ((hw_cfg->cu_size_mode & 0x4) == 0) && ((align_32_width_flag != 0) || (align_32_height_flag != 0)) ) { + mpp_err_f("CFG FAIL : Picture width and height must be aligned with 32 pixels when enable CU32x32 of cuSizeMode\n"); + mpp_err_f("RECOMMEND CONFIG PARAMETER : cuSizeMode |= 0x4 (CU32x32)\n"); + return MPP_NOK; + } + } + + // multi-slice & wpp + if (hw_cfg->wpp_enable == 1 && (hw_cfg->independ_slice_mode != 0 || hw_cfg->depend_slice_mode != 0)) { + mpp_err_f("CFG FAIL : If WaveFrontSynchro(WPP) '1', the option of multi-slice must be '0'\n"); + mpp_err_f("RECOMMEND CONFIG PARAMETER : independSliceMode = 0, dependSliceMode = 0\n"); + return MPP_NOK; + } + } + + // check multi slice + { + if (hw_cfg->independ_slice_mode == 0 && hw_cfg->depend_slice_mode != 0) { + mpp_err_f("CFG FAIL : If independSliceMode is '0', dependSliceMode must be '0'\n"); + mpp_err_f("RECOMMEND CONFIG PARAMETER : independSliceMode = 1, independSliceModeArg = TotalCtuNum\n"); + return MPP_NOK; + } else if ((hw_cfg->independ_slice_mode == 1) && (hw_cfg->depend_slice_mode == 1) ) { + if (hw_cfg->independ_slice_mode_arg < hw_cfg->depend_slice_mode_arg) { + mpp_err_f("CFG FAIL : If independSliceMode & dependSliceMode is both '1'(multi-slice with ctu count)," + "must be independSliceModeArg >= dependSliceModeArg\n"); + mpp_err_f("RECOMMEND CONFIG PARAMETER : dependSliceMode = 0\n"); + return MPP_NOK; + } + } + + if (hw_cfg->independ_slice_mode != 0) { + if (hw_cfg->independ_slice_mode_arg > 65535) { + mpp_err_f("CFG FAIL : If independSliceMode is not 0," + "must be independSliceModeArg <= 0xFFFF\n"); + return MPP_NOK; + } + } + + if (hw_cfg->depend_slice_mode != 0) { + if (hw_cfg->depend_slice_mode_arg > 65535) { + mpp_err_f("CFG FAIL : If dependSliceMode is not 0," + "must be dependSliceModeArg <= 0xFFFF\n"); + return MPP_NOK; + } + } + } + + if (hw_cfg->conf_win_top % 2) { + mpp_err_f("CFG FAIL : conf_win_top : %d value is not available." + "The value should be equal to multiple of 2.\n", hw_cfg->conf_win_top); + return MPP_NOK; + } + + if (hw_cfg->conf_win_bot % 2) { + mpp_err_f("CFG FAIL : conf_win_bot : %d value is not available." + "The value should be equal to multiple of 2.\n", hw_cfg->conf_win_bot); + return MPP_NOK; + } + + if (hw_cfg->conf_win_left % 2) { + mpp_err_f("CFG FAIL : conf_win_left : %d value is not available." + "The value should be equal to multiple of 2.\n", hw_cfg->conf_win_left); + return MPP_NOK; + } + + if (hw_cfg->conf_win_right % 2) { + mpp_err_f( "CFG FAIL : conf_win_right : %d value is not available." + "The value should be equal to multiple of 2.\n", hw_cfg->conf_win_right); + return MPP_NOK; + } + + if (hw_cfg->rc_enable) { + ret = vepu22_check_rc_parameter(ctx); + } + hal_h265e_dbg_func("leave\n"); + return ret; +} + +static MPP_RET vepu22_set_prep_cfg(HalH265eCtx* ctx) +{ + hal_h265e_dbg_func("enter\n"); + + HalH265eCfg *hw_cfg = (HalH265eCfg *)ctx->hw_cfg; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hw_cfg->width = prep->width; + hw_cfg->height = prep->height; + hw_cfg->width_stride = MPP_ALIGN(prep->hor_stride, 16);// 32 + hw_cfg->height_stride = prep->height; + hw_cfg->src_format = vepu22_get_yuv_format(prep->format); + hal_h265e_dbg_input("width = %d,height = %d", + hw_cfg->width, hw_cfg->height); + hal_h265e_dbg_input("width_stride = %d,height_stride = %d", + hw_cfg->width_stride, hw_cfg->height_stride); + hal_h265e_dbg_input("src_format = %d", hw_cfg->src_format); + + hal_h265e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET vepu22_check_rc_cfg_change(HalH265eCtx* ctx, MppEncRcCfg* set) +{ + hal_h265e_dbg_func("enter"); + + hal_h265e_dbg_func("set = %p\n", set); + hal_h265e_dbg_input("rc_mode = %d,quality = %d,bps_target = %d\n", + set->rc_mode, set->quality, set->bps_target); + hal_h265e_dbg_input("fps_in_flex = %d,fps_out_flex = %d\n", + set->fps_in_flex, set->fps_out_flex); + hal_h265e_dbg_input("fps_in_denorm = %d,fps_out_flex = %d\n", + set->fps_in_num, set->fps_in_denorm); + hal_h265e_dbg_input("fps_out_num = %d,fps_out_denorm = %d\n", + set->fps_out_num, set->fps_out_denorm); + hal_h265e_dbg_input("gop = %d,skip_cnt = %d\n", set->gop, set->skip_cnt); + if (ctx->init == 0) { + set->change = MPP_ENC_RC_CFG_CHANGE_ALL; + ctx->option |= H265E_SET_RC_CFG; + hal_h265e_dbg_input("init = 0, cfg all"); + } + + hal_h265e_dbg_func("leave"); + return MPP_OK; +} + +static MPP_RET vepu22_set_rc_cfg(HalH265eCtx* ctx) +{ + hal_h265e_dbg_func("enter\n"); + + HalH265eCfg *cfg = (HalH265eCfg*)&ctx->hw_cfg; + MppEncRcCfg *rc = &ctx->set->rc; + + hal_h265e_dbg_input("rc_mode = %d,quality = %d,bps_target = %d\n", + rc->rc_mode, rc->quality, rc->bps_target); + hal_h265e_dbg_input("fps_in_flex = %d,fps_out_flex = %d\n", + rc->fps_in_flex, rc->fps_out_flex); + hal_h265e_dbg_input("fps_in_denorm = %d,fps_out_flex = %d\n", + rc->fps_in_num, rc->fps_in_denorm); + hal_h265e_dbg_input("fps_out_num = %d,fps_out_denorm = %d\n", + rc->fps_out_num, rc->fps_out_denorm); + hal_h265e_dbg_input("gop = %d,skip_cnt = %d\n", rc->gop, rc->skip_cnt); + + /* the first time to set rc cfg*/ + if (rc->change & MPP_ENC_RC_CFG_CHANGE_FPS_OUT) { + hal_h265e_dbg_input("FPS change\n"); + cfg->frame_rate = rc->fps_out_num / rc->fps_out_denorm; + cfg->time_scale = cfg->frame_rate * cfg->num_units_in_tick; + cfg->cfg_mask |= (H265E_CFG_SET_TIME_SCALE | H265E_CFG_SET_NUM_UNITS_IN_TICK); + cfg->cfg_option |= H265E_PARAM_CHANEGED_COMMON; + } + + int rc_change = ((rc->change & MPP_ENC_RC_CFG_CHANGE_RC_MODE) + || (rc->change & MPP_ENC_RC_CFG_CHANGE_BPS)); + if (rc_change) { + hal_h265e_dbg_input("rc change = %d\n", rc->change); + cfg->rc_enable = 0; + switch (rc->rc_mode) { + case MPP_ENC_RC_MODE_VBR: + // if rc_mode is VBR and quality == MPP_ENC_RC_QUALITY_CQP, this mode is const QP + if (rc->quality == MPP_ENC_RC_QUALITY_CQP) { + cfg->rc_enable = 0; // fix qp + cfg->bit_rate = 0; + cfg->trans_rate = 0; + } else { + cfg->rc_enable = 1; + cfg->bit_rate = rc->bps_target; + // set trans_rate larger than bit_rate + cfg->trans_rate = cfg->bit_rate + 10000; + } + break; + case MPP_ENC_RC_MODE_CBR: + cfg->rc_enable = 1; + cfg->bit_rate = rc->bps_target; + cfg->trans_rate = cfg->bit_rate; + break; + default: + mpp_err_f("rc_mode = %d not support", rc->rc_mode); + } + + cfg->cfg_mask |= (H265E_CFG_RC_PARAM_CHANGE | H265E_CFG_RC_TARGET_RATE_CHANGE + | H265E_CFG_RC_TRANS_RATE_CHANGE); + //cfg->cfg_mask |= (H265E_CFG_RC_TARGET_RATE_CHANGE | H265E_CFG_RC_MIN_MAX_QP_CHANGE); + cfg->cfg_option |= H265E_PARAM_CHANEGED_COMMON; + } + + + hal_h265e_dbg_input("rc_enable = %d\n", cfg->rc_enable); + hal_h265e_dbg_input("bit_rate = %d,trans_rate = %d\n", cfg->bit_rate, cfg->trans_rate); + hal_h265e_dbg_func("leave,enter cfg->cfg_mask = 0x%x,cfg->cfg_option = 0x%x\n", + cfg->cfg_mask, cfg->cfg_option); + return MPP_OK; +} + +static MPP_RET vepu22_check_code_cfg_change(HalH265eCtx* ctx, MppEncH265Cfg* set) +{ + if (ctx == NULL || set == NULL) { + return MPP_NOK; + } + hal_h265e_dbg_func("enter"); + MppEncH265Cfg* cfg = &ctx->cfg->codec.h265; + if (ctx->init == 0) { + ctx->option |= H265E_SET_CODEC_CFG; + if (set->change & MPP_ENC_H265_CFG_INTRA_QP_CHANGE) { + cfg->intra_qp = set->intra_qp; + } + hal_h265e_dbg_input("init = 0, cfg all,change = 0x%x", set->change); + } else { + hal_h265e_dbg_func("enter cfg->cfg_mask = 0x%x,cfg->cfg_option = 0x%x", + ((HalH265eCfg *)ctx->hw_cfg)->cfg_mask, + ((HalH265eCfg *)ctx->hw_cfg)->cfg_option); + hal_h265e_dbg_func(" change = %d", set->change); + hal_h265e_dbg_input("hw_cfg->intra_qp = %d,const_intra_pred = %d", + set->intra_qp, set->const_intra_pred); + hal_h265e_dbg_input("intra_refresh_mode = %d,intra_refresh_arg = %d\n", + set->intra_refresh_mode, set->intra_refresh_arg); + hal_h265e_dbg_input("independ_slice_mode = %d,independ_slice_mode_arg = %d\n", + set->independ_slice_mode, set->independ_slice_arg); + hal_h265e_dbg_input("depend_slice_mode = %d,depend_slice_mode_arg = %d\n", + set->depend_slice_mode, set->depend_slice_arg); + + if (set->change & MPP_ENC_H265_CFG_INTRA_QP_CHANGE) { + cfg->intra_qp = set->intra_qp; + } + + if (set->change & MPP_ENC_H265_CFG_RC_QP_CHANGE) { + cfg->max_qp = set->max_qp; + cfg->min_qp = set->min_qp; + cfg->max_delta_qp = set->max_delta_qp; + } + + if (set->change & MPP_ENC_H265_CFG_INTRA_REFRESH_CHANGE) { + cfg->intra_refresh_mode = set->intra_refresh_mode; + cfg->intra_refresh_arg = set->intra_refresh_arg; + } + + if (set->change & MPP_ENC_H265_CFG_INDEPEND_SLICE_CHANGE) { + cfg->independ_slice_mode = set->independ_slice_mode; + cfg->independ_slice_arg = set->independ_slice_arg; + } + + if (set->change & MPP_ENC_H265_CFG_DEPEND_SLICE_CHANGE) { + cfg->depend_slice_mode = set->depend_slice_mode; + cfg->depend_slice_arg = set->depend_slice_arg; + } + + cfg->change = set->change; + } + hal_h265e_dbg_func("leave"); + return MPP_OK; +} + +static MPP_RET vepu22_set_codec_cfg(HalH265eCtx* ctx) +{ + MppEncH265Cfg* codec = &ctx->cfg->codec.h265; + HalH265eCfg* cfg = (HalH265eCfg*)&ctx->hw_cfg; + RK_U32 change = codec->change; + + hal_h265e_dbg_func("enter change = %d", codec->change); + hal_h265e_dbg_input("hw_cfg->intra_qp = %d,const_intra_pred = %d", + cfg->intra_qp, codec->const_intra_pred); + hal_h265e_dbg_input("intra_refresh_mode = %d,intra_refresh_arg = %d\n", + codec->intra_refresh_mode, codec->intra_refresh_arg); + hal_h265e_dbg_input("independ_slice_mode = %d,independ_slice_mode_arg = %d\n", + codec->independ_slice_mode, codec->independ_slice_arg); + hal_h265e_dbg_input("depend_slice_mode = %d,depend_slice_mode_arg = %d\n", + codec->depend_slice_mode, codec->depend_slice_arg); + + if (change & MPP_ENC_H265_CFG_INTRA_REFRESH_CHANGE) { + cfg->intra_refresh_mode = codec->intra_refresh_mode; + cfg->intra_refresh_arg = codec->intra_refresh_arg; + cfg->intra_in_inter_slice_enable = (cfg->intra_refresh_mode != 0) ? 1 : 0; + + cfg->cfg_mask |= (H265E_CFG_PARAM_CHANGE | H265E_CFG_INTRA_REFRESH_CHANGE); + cfg->cfg_option |= H265E_PARAM_CHANEGED_COMMON; + } + + if (change & MPP_ENC_H265_CFG_INDEPEND_SLICE_CHANGE) { + cfg->independ_slice_mode = codec->independ_slice_mode; + cfg->independ_slice_mode_arg = codec->independ_slice_arg; + + cfg->cfg_mask |= H265E_CFG_INDEPENDENT_SLICE_CHANGE; + cfg->cfg_option |= H265E_PARAM_CHANEGED_COMMON; + } + + if (change & MPP_ENC_H265_CFG_DEPEND_SLICE_CHANGE) { + cfg->depend_slice_mode = codec->depend_slice_mode; + cfg->depend_slice_mode_arg = codec->depend_slice_arg; + + cfg->cfg_mask |= H265E_CFG_DEPENDENT_SLICE_CHANGE; + cfg->cfg_option |= H265E_PARAM_CHANEGED_COMMON; + } + + if (change & MPP_ENC_H265_CFG_DEPEND_SLICE_CHANGE) { + cfg->depend_slice_mode = codec->depend_slice_mode; + cfg->depend_slice_mode_arg = codec->depend_slice_arg; + + cfg->cfg_mask |= H265E_CFG_DEPENDENT_SLICE_CHANGE; + cfg->cfg_option |= H265E_PARAM_CHANEGED_COMMON; + } + cfg->sao_enable = codec->sao_enable; + if (change & MPP_ENC_H265_CFG_FRAME_RATE_CHANGE) { + cfg->time_scale = cfg->frame_rate * 1000; + cfg->cfg_mask |= H265E_CFG_FRAME_RATE_CHANGE; + cfg->cfg_option |= H265E_PARAM_CHANEGED_COMMON; + } + + cfg->initial_rc_qp = cfg->max_qp; + cfg->const_intra_pred_flag = codec->const_intra_pred; + + if (change & MPP_ENC_H265_CFG_INTRA_QP_CHANGE) { + hal_h265e_dbg_input("intra qp %d change %d", cfg->intra_qp, codec->intra_qp); + cfg->intra_qp = codec->intra_qp; + + cfg->cfg_mask |= H265E_CFG_INTRA_PARAM_CHANGE; + cfg->cfg_option |= H265E_PARAM_CHANEGED_COMMON; + } + + if (change & MPP_ENC_H265_CFG_RC_QP_CHANGE) { + cfg->max_qp = codec->max_qp; + cfg->min_qp = codec->min_qp; + cfg->max_delta_qp = codec->max_delta_qp; + + cfg->cfg_mask |= H265E_CFG_RC_MIN_MAX_QP_CHANGE; + cfg->cfg_option |= H265E_PARAM_CHANEGED_COMMON; + } + hal_h265e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET vepu22_set_gop_cfg(HalH265eCtx* ctx) +{ + hal_h265e_dbg_func("enter\n"); + + HalH265eCfg* hw_cfg = (HalH265eCfg*)ctx->hw_cfg; + MppEncRcCfg* rc = &ctx->set->rc; + MppEncH265Cfg* codec = &ctx->cfg->codec.h265; + + hal_h265e_dbg_input("gop = %d,const_intra_pred = %d\n", + rc->gop, codec->const_intra_pred); + hal_h265e_dbg_input("intra_qp = %d,gop_delta_qp = %d\n", + codec->intra_qp, codec->gop_delta_qp); + if ((rc->change & MPP_ENC_RC_CFG_CHANGE_GOP) || + (codec->change & MPP_ENC_H265_CFG_INTRA_QP_CHANGE)) { + hw_cfg->cfg_mask |= (H265E_CFG_INTRA_PARAM_CHANGE | H265E_CFG_GOP_PARAM_CHANGE); + hal_h265e_dbg_input("%d,hw_cfg->cfg_mask = %d\n", __LINE__, hw_cfg->cfg_mask); + hw_cfg->cfg_option |= (H265E_PARAM_CHANEGED_COMMON | H265E_PARAM_CHANEGED_CUSTOM_GOP); + + hw_cfg->intra_period = rc->gop; + + /* not change custom_gop_size */ + // hw_cfg->gop.custom_gop_size = H265E_MAX_GOP_NUM; + //(rc->gop > H265E_MAX_GOP_NUM) ? H265E_MAX_GOP_NUM : rc->gop; + if (hw_cfg->intra_period == 1) { + hw_cfg->gop_idx = PRESET_IDX_ALL_I; + } else { + hw_cfg->gop_idx = PRESET_IDX_CUSTOM_GOP; + } + + hal_h265e_dbg_input("%d,hw_cfg->cfg_mask = %d\n", __LINE__, hw_cfg->cfg_mask); + hal_h265e_dbg_input("hw_cfg->gop_idx= %d,hw_cfg->gop.custom_gop_size = %d\n", + hw_cfg->gop_idx, hw_cfg->gop.custom_gop_size); + if (hw_cfg->gop_idx == PRESET_IDX_CUSTOM_GOP) { + RK_U32 i = 0; + for (i = 0; i < hw_cfg->gop.custom_gop_size; i++) { + if (i == 0) { + hw_cfg->gop.pic[i].ref_poc_l0 = 0; + } else { + hw_cfg->gop.pic[i].ref_poc_l0 = i - 1; + } + hw_cfg->gop.pic[i].type = H265E_PIC_TYPE_P; + //not set pocOffset to 0,because the first I frame's will be take the pocOffset 0 + hw_cfg->gop.pic[i].offset = i + 1; + hw_cfg->gop.pic[i].qp = codec->intra_qp + codec->gop_delta_qp; + hw_cfg->gop.pic[i].ref_poc_l1 = 0; + hw_cfg->gop.pic[i].temporal_id = 0; + hw_cfg->gop.gop_pic_lambda[i] = 0; + } + } + + } + + hal_h265e_dbg_input("gop_idx = %d,intra_period = %d\n", + hw_cfg->gop_idx, hw_cfg->intra_period); + hal_h265e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET vepu22_dump_cfg(HalH265eCtx* ctx) +{ + HalH265eCfg* hw_cfg = (HalH265eCfg*)&ctx->hw_cfg; + hal_h265e_dbg_func("enter\n"); + + hal_h265e_dbg_input("profile = %d,level = %d,tier = %d\n", + hw_cfg->profile, hw_cfg->level, hw_cfg->tier); + hal_h265e_dbg_input("chroma_idc = %d\n", hw_cfg->chroma_idc); + hal_h265e_dbg_input("width = %d,height = %d\n", hw_cfg->width, hw_cfg->height); + hal_h265e_dbg_input("width_stride = %d,height_stride = %d\n", + hw_cfg->width_stride, hw_cfg->height_stride); + hal_h265e_dbg_input("bit_depth = %d,src_format = %d,src_endian = %d\n", + hw_cfg->bit_depth, hw_cfg->src_format, hw_cfg->src_endian ); + hal_h265e_dbg_input("bs_endian = %d,src_format = %d\n", + hw_cfg->bs_endian, hw_cfg->fb_endian); + hal_h265e_dbg_input("frame_rate = %d,frame_skip = %d\n", + hw_cfg->frame_rate, hw_cfg->frame_skip); + hal_h265e_dbg_input("111 bit_rate = %d,trans_rate = %d\n", + hw_cfg->bit_rate, hw_cfg->trans_rate); + hal_h265e_dbg_input("fbc_map_type = %d,line_buf_int_en = %d\n", + hw_cfg->fbc_map_type, hw_cfg->line_buf_int_en); + hal_h265e_dbg_input("slice_int_enable = %d,ring_buffer_enable = %d\n", + hw_cfg->slice_int_enable, hw_cfg->ring_buffer_enable); + hal_h265e_dbg_input("lossless_enable = %d,const_intra_pred_flag = %d\n", + hw_cfg->lossless_enable, hw_cfg->const_intra_pred_flag); + hal_h265e_dbg_input("chroma_cb_qp_offset = %d,chroma_cr_qp_offset = %d\n", + hw_cfg->chroma_cb_qp_offset, hw_cfg->chroma_cr_qp_offset); + hal_h265e_dbg_input("gop_idx = %d,decoding_refresh_type = %d\n", + hw_cfg->gop_idx, hw_cfg->decoding_refresh_type); + hal_h265e_dbg_input("intra_qp = %d,intra_period = %d\n", + hw_cfg->intra_qp, hw_cfg->intra_period); + hal_h265e_dbg_input("conf_win_top = %d,conf_win_bot = %d,conf_win_left = %d,conf_win_right = %d\n", + hw_cfg->conf_win_top, hw_cfg->conf_win_bot, hw_cfg->conf_win_left, hw_cfg->conf_win_right); + hal_h265e_dbg_input("independ_slice_mode = %d,independ_slice_mode_arg = %d\n", + hw_cfg->independ_slice_mode, hw_cfg->independ_slice_mode_arg); + hal_h265e_dbg_input("depend_slice_mode = %d,depend_slice_mode_arg = %d\n", + hw_cfg->depend_slice_mode, hw_cfg->depend_slice_mode_arg); + hal_h265e_dbg_input("intra_refresh_mode = %d,intra_refresh_arg = %d\n", + hw_cfg->intra_refresh_mode, hw_cfg->intra_refresh_arg); + hal_h265e_dbg_input("use_recommend_param = %d,scaling_list_enable = %d\n", + hw_cfg->use_recommend_param, hw_cfg->scaling_list_enable); + hal_h265e_dbg_input("cu_size_mode = %d,tmvp_enable = %d\n", + hw_cfg->cu_size_mode, hw_cfg->tmvp_enable); + hal_h265e_dbg_input("wpp_enable = %d,max_num_merge = %d\n", + hw_cfg->wpp_enable, hw_cfg->max_num_merge); + hal_h265e_dbg_input("dynamic_merge_8x8_enable = %d,dynamic_merge_16x16_enable = %d\n", + hw_cfg->dynamic_merge_8x8_enable, hw_cfg->dynamic_merge_16x16_enable, + hw_cfg->dynamic_merge_32x32_enable); + hal_h265e_dbg_input("disable_deblk = %d,lf_cross_slice_boundary_enable = %d\n", + hw_cfg->disable_deblk, hw_cfg->lf_cross_slice_boundary_enable); + hal_h265e_dbg_input("beta_offset_div2 = %d,tc_offset_div2 = %d\n", + hw_cfg->beta_offset_div2, hw_cfg->tc_offset_div2); + hal_h265e_dbg_input("skip_intra_trans = %d,sao_enable = %d\n", + hw_cfg->skip_intra_trans, hw_cfg->sao_enable); + hal_h265e_dbg_input("intra_in_inter_slice_enable = %d,intra_nxn_enable = %d\n", + hw_cfg->intra_in_inter_slice_enable, hw_cfg->intra_nxn_enable); + hal_h265e_dbg_input("intra_qp_offset = %d,init_buf_levelx8 = %d\n", + hw_cfg->intra_qp_offset, hw_cfg->init_buf_levelx8); + hal_h265e_dbg_input("bit_alloc_mode = %d,rc_enable = %d\n", + hw_cfg->bit_alloc_mode, hw_cfg->rc_enable); + hal_h265e_dbg_input("cu_level_rc_enable = %d,hvs_qp_enable = %d\n", + hw_cfg->cu_level_rc_enable, hw_cfg->hvs_qp_enable); + hal_h265e_dbg_input("hvs_qp_scale_enable = %d,hvs_qp_scale = %d\n", + hw_cfg->hvs_qp_scale_enable, hw_cfg->hvs_qp_scale); + hal_h265e_dbg_input("min_qp = %d,max_qp = %d,max_delta_qp = %d\n", + hw_cfg->min_qp, hw_cfg->max_qp, hw_cfg->max_delta_qp); + hal_h265e_dbg_input("num_units_in_tick = %d,time_scale = %d\n", + hw_cfg->num_units_in_tick, hw_cfg->time_scale); + hal_h265e_dbg_input("initial_rc_qp = %d,num_ticks_poc_diff_one = %d\n", + hw_cfg->initial_rc_qp, hw_cfg->num_ticks_poc_diff_one); + hal_h265e_dbg_input("nr_noise_est_enable = %d\n", + hw_cfg->nr_noise_est_enable); + hal_h265e_dbg_input("intra_min_qp = %d,intra_max_qp = %d\n", + hw_cfg->intra_min_qp, hw_cfg->intra_max_qp); + hal_h265e_dbg_input("roi_enable = %d,roi_delta_qp = %d\n", + hw_cfg->ctu.roi_enable, hw_cfg->ctu.roi_delta_qp); + hal_h265e_dbg_input("ctu_qp_enable = %d\n", hw_cfg->ctu.ctu_qp_enable); + hal_h265e_dbg_input("ROI/CTU map_endian = %d,map_stride = %d\n", + hw_cfg->ctu.map_endian, hw_cfg->ctu.map_stride); + hal_h265e_dbg_input("initial_delay = %d,hrd_rbsp_in_vps = %d\n", + hw_cfg->initial_delay, hw_cfg->hrd_rbsp_in_vps); + hal_h265e_dbg_input("hrd_rbsp_in_vui = %d\n", + hw_cfg->hrd_rbsp_in_vui); + hal_h265e_dbg_input("use_long_term = %d,use_cur_as_longterm_pic = %d,use_longterm_ref = %d\n", + hw_cfg->use_long_term, hw_cfg->use_cur_as_longterm_pic, hw_cfg->use_longterm_ref); + hal_h265e_dbg_input("cfg_option = %d,cfg_mask = %d \n", + hw_cfg->cfg_option, hw_cfg->cfg_mask); + + hal_h265e_dbg_func("leave\n"); + return MPP_OK; +} + + +static MPP_RET vepu22_set_cfg(HalH265eCtx* ctx) +{ + MPP_RET ret = MPP_OK; + hal_h265e_dbg_func("enter hal"); + if (ctx == NULL) { + mpp_err_f("error: ctx == NULL"); + return MPP_NOK; + } + + if (vepu22_set_prep_cfg(ctx) != MPP_OK) { + mpp_err_f("error: h265e_init_hal_prep_cfg fail\n"); + return MPP_NOK; + } + + if (vepu22_set_rc_cfg(ctx) != MPP_OK) { + mpp_err_f("error: h265e_hal_set_rc_cfg fail\n"); + return MPP_NOK; + } + + if (vepu22_set_codec_cfg(ctx) != MPP_OK) { + mpp_err_f("error: h265e_hal_set_codec_cfg fail\n"); + return MPP_NOK; + } + + if (vepu22_set_gop_cfg(ctx) != MPP_OK) { + mpp_err_f("error: h265e_hal_set_gop_cfg fail\n"); + return MPP_NOK; + } + + if (vepu22_check_encode_parameter(ctx) != MPP_OK) { + mpp_err_f("check encode prameter fail\n"); + return MPP_NOK; + } + + vepu22_dump_cfg(ctx); + + + if (ctx->dev_ctx) { + ret = mpp_device_send_reg_with_id(ctx->dev_ctx, H265E_SET_PARAMETER, + ctx->hw_cfg, sizeof(struct hal_h265e_cfg)); + hal_h265e_dbg_input("hal_h265e_send_cmd ret = %d\n", ret); + if (ret) { + mpp_err_f("error: hal_h265e_set_param 0x%x fail\n", ret); + return MPP_NOK; + } + } + + vepu22_clear_cfg_mask(ctx); + hal_h265e_dbg_func("leave hal"); + return ret; +} + +MPP_RET hal_h265e_vepu22_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + HalH265eCtx* ctx = (HalH265eCtx*)hal; + + hal_h265e_dbg_func("enter hal\n", hal); + ctx->buf_grp = NULL; + ctx->roi = NULL; + ctx->ctu = NULL; + + /* pointer to cfg define in controller*/ + ctx->cfg = cfg->cfg; + ctx->set = cfg->set; + ctx->int_cb = cfg->hal_int_cb; + ctx->option = H265E_SET_CFG_INIT; + ctx->init = 0; + + ctx->hw_cfg = mpp_calloc_size(void, sizeof(HalH265eCfg)); + if (ctx->hw_cfg == NULL) { + mpp_err("failed to malloc ctx->hw_cfg %d\n", ctx->hw_cfg); + ret = MPP_ERR_MALLOC; + goto FAIL; + } + vepu22_set_default_hw_cfg(ctx->hw_cfg); + + ctx->en_info = mpp_calloc_size(void, sizeof(EncInfo)); + if (ctx->en_info == NULL) { + mpp_err("failed to malloc ctx->en_info %d\n", ctx->en_info); + ret = MPP_ERR_MALLOC; + goto FAIL; + } + + if (HAL_H265E_DBG_WRITE_IN_STREAM & hal_h265e_debug) { + ctx->mInFile = fopen("/data/h265e/h265e_yuv.bin", "wb"); + if (ctx->mInFile == NULL) { + mpp_err_f("open /data/h265e_yuv.bin fail\n"); + } + } + + if (HAL_H265E_DBG_WRITE_OUT_STREAM & hal_h265e_debug) { + ctx->mOutFile = fopen("/data/h265e/h265e_bs.bin", "wb"); + if (ctx->mOutFile == NULL) { + mpp_err_f("open /data/h265e/h265e_bs.bin fail\n"); + } + } + + ret = mpp_buffer_group_get_internal(&ctx->buf_grp, MPP_BUFFER_TYPE_ION); + if (ret) { + mpp_err("failed to malloc buf_grp from ion ret %d\n", ret); + goto FAIL; + } + + //!< mpp_device_init + MppDevCfg dev_cfg = { + .type = MPP_CTX_ENC, /* type */ + .coding = MPP_VIDEO_CodingHEVC, /* coding */ + .platform = 0, /* platform */ + .pp_enable = 0, /* pp_enable */ + }; + + ret = mpp_device_init(&ctx->dev_ctx, &dev_cfg); + if (ret) { + mpp_err("mpp_device_init failed ret: %d\n", ret); + goto FAIL; + } + hal_h265e_dbg_func("leave hal %p\n", hal); + return MPP_OK; +FAIL: + if (ctx->hw_cfg != NULL) { + mpp_free(ctx->hw_cfg); + ctx->hw_cfg = NULL; + } + + if (ctx->en_info != NULL) { + mpp_free(ctx->en_info); + ctx->en_info = NULL; + } + + if (ctx->roi != NULL) { + mpp_buffer_put(ctx->roi); + ctx->roi = NULL; + } + + if (ctx->ctu != NULL) { + mpp_buffer_put(ctx->ctu); + ctx->ctu = NULL; + } + + if (ctx->buf_grp != NULL) { + mpp_buffer_group_put(ctx->buf_grp); + ctx->buf_grp = NULL; + } + + if (ctx->mInFile != NULL) { + fclose(ctx->mInFile); + ctx->mInFile = NULL; + } + + if (ctx->mOutFile != NULL) { + fclose(ctx->mOutFile); + ctx->mOutFile = NULL; + } + + return MPP_NOK; +} + +MPP_RET hal_h265e_vepu22_deinit(void *hal) +{ + HalH265eCtx* ctx = (HalH265eCtx*)hal; + + hal_h265e_dbg_func("enter hal %p\n", hal); + + if (ctx->hw_cfg != NULL) { + mpp_free(ctx->hw_cfg); + ctx->hw_cfg = NULL; + } + + if (ctx->en_info != NULL) { + mpp_free(ctx->en_info); + ctx->en_info = NULL; + } + + if (ctx->roi != NULL) { + mpp_buffer_put(ctx->roi); + ctx->roi = NULL; + } + + if (ctx->ctu != NULL) { + mpp_buffer_put(ctx->ctu); + ctx->ctu = NULL; + } + + if (ctx->buf_grp != NULL) { + mpp_buffer_group_put(ctx->buf_grp); + ctx->buf_grp = NULL; + } + + if (ctx->dev_ctx) { + mpp_device_deinit(ctx->dev_ctx); + ctx->dev_ctx = NULL; + } + + if (ctx->mInFile != NULL) { + fflush(ctx->mInFile); + fclose(ctx->mInFile); + ctx->mInFile = NULL; + } + + if (ctx->mOutFile != NULL) { + fflush(ctx->mOutFile); + fclose(ctx->mOutFile); + ctx->mOutFile = NULL; + } + hal_h265e_dbg_func("leave hal %p\n", hal); + return MPP_OK; +} + +MPP_RET hal_h265e_vepu22_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + + HalH265eCtx* ctx = (HalH265eCtx*)hal; + HalEncTask *info = &task->enc; + MppBuffer input = info->input; + MppBuffer output = info->output; + H265eSyntax *syntax = (H265eSyntax *)info->syntax.data; + EncInfo* en_info = (EncInfo*)ctx->en_info; + + hal_h265e_dbg_func("enter hal %p\n", hal); + memset(en_info, 0, sizeof(EncInfo)); + + en_info->src_addr = mpp_buffer_get_fd(input); + en_info->src_size = mpp_buffer_get_size(input); + if (ctx->mInFile != NULL) { + RK_U8*buffer = mpp_buffer_get_ptr(input); + if (buffer != NULL && en_info->src_size > 0) { + fwrite(buffer, en_info->src_size, 1, ctx->mInFile); + fflush(ctx->mInFile); + hal_h265e_dbg_input("H265E: write yuv's data to file,size = %d", + en_info->src_size); + } + } + + /* + * Minimum size of bitstream buffer : 96KBytes + */ + en_info->bs_addr = mpp_buffer_get_fd(output); + en_info->bs_size = mpp_buffer_get_size(output); + + vepu22_set_roi_region(ctx); + vepu22_set_ctu_qp(ctx); + vepu22_set_frame_type(syntax, en_info); + hal_h265e_dbg_func("leave hal %p, frame type = %d,enable = %d\n", + hal, en_info->force_frame_type, en_info->force_frame_type_enable); + + return ret; +} + +MPP_RET hal_h265e_vepu22_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalH265eCtx* ctx = (HalH265eCtx*)hal; + + hal_h265e_dbg_func("enter hal %p\n", hal); + + ret = mpp_device_send_reg(ctx->dev_ctx, (RK_U32*)ctx->en_info, + sizeof(EncInfo) / sizeof(RK_U32)); + if (ret) { + ret = MPP_ERR_VPUHW; + mpp_err_f("h265 encoder FlushRegs fail. \n"); + } + + hal_h265e_dbg_func("leave hal %p\n", hal); + + (void)task; + return ret; +} + +MPP_RET hal_h265e_vepu22_wait(void *hal, HalTaskInfo *task) +{ + RK_S32 ret = MPP_NOK; + + HalH265eCtx* ctx = (HalH265eCtx*)hal; + HalEncTask *info = &task->enc; + H265eFeedback feedback; + H265eVepu22Result result; + MppBuffer output = info->output; + + hal_h265e_dbg_func("enter hal %p\n", hal); + + ret = mpp_device_wait_reg(ctx->dev_ctx, (RK_U32*)&result, + (RK_U32)(sizeof(H265eVepu22Result) / sizeof(RK_U32))); + if (ret) { + mpp_err_f("leave hal hardware returns error:%d\n", ret); + return MPP_ERR_VPUHW; + } + + info->is_intra = 0; + feedback.status = result.fail_reason; + if (feedback.status == 0) { + void* buffer = NULL; + int size = 0; + + feedback.bs_size = result.bs_size; + feedback.pic_type = result.pic_type; + feedback.avg_ctu_qp = result.avg_ctu_qp; + feedback.gop_idx = result.gop_idx; + feedback.poc = result.poc; + feedback.src_idx = result.src_idx; + feedback.enc_pic_cnt = result.enc_pic_cnt; + + if (feedback.pic_type == H265E_PIC_TYPE_I || + feedback.pic_type == H265E_PIC_TYPE_IDR || + feedback.pic_type == H265E_PIC_TYPE_CRA) { + info->is_intra = 1; + } else { + info->is_intra = 0; + } + buffer = mpp_buffer_get_ptr(output); + size = result.bs_size; + if (ctx->mOutFile != NULL && size > 0) { + fwrite(buffer, size, 1, ctx->mOutFile); + fflush(ctx->mOutFile); + hal_h265e_dbg_input("H265E: write data bs to file,size = %d", size); + } + } else { + // error + feedback.bs_size = 0; + } + + ctx->int_cb.callBack(ctx->int_cb.opaque, &feedback); + task->enc.length = feedback.bs_size; + hal_h265e_dbg_func("leave hal %p,status = %d,size = %d\n", + hal, feedback.status, feedback.bs_size); + + return MPP_OK; +} + +MPP_RET hal_h265e_vepu22_reset(void *hal) +{ + MPP_RET ret = MPP_OK; + HalH265eCtx* ctx = (HalH265eCtx*)hal; + + hal_h265e_dbg_func("enter hal %p\n", hal); + + if (ctx->dev_ctx) { + ret = mpp_device_send_reg_with_id(ctx->dev_ctx, H265E_RESET, NULL, 0); + if (ret) { + ret = MPP_ERR_VPUHW; + mpp_err_f("failed to send reset cmd\n"); + } + } + + hal_h265e_dbg_func("leave hal %p\n", hal); + + return ret; +} + +MPP_RET hal_h265e_vepu22_flush(void *hal) +{ + HalH265eCtx* ctx = (HalH265eCtx*)hal; + + hal_h265e_dbg_func("enter hal %p\n", hal); + hal_h265e_dbg_func("leave hal %p\n", hal); + + (void)ctx; + return MPP_OK; +} + +MPP_RET hal_h265e_vepu22_control(void *hal, RK_S32 cmd_type, void *param) +{ + MPP_RET ret = MPP_OK; + RK_U32 change = 0; + + HalH265eCtx *ctx = (HalH265eCtx*)hal; + HalH265eCfg *hw_cfg = (HalH265eCfg *)ctx->hw_cfg; + + hal_h265e_dbg_func("enter hal %p,cmd = %d\n", hal, cmd_type); + switch (cmd_type) { + case MPP_ENC_SET_EXTRA_INFO: { + hal_h265e_dbg_input("MPP_ENC_SET_EXTRA_INFO\n"); + break; + } + + case MPP_ENC_GET_EXTRA_INFO: { + hal_h265e_dbg_input("MPP_ENC_GET_EXTRA_INFO\n"); + MppPacket *pkt_out = (MppPacket *)param; + *pkt_out = NULL; + break; + } + + case MPP_ENC_SET_PREP_CFG: { + MppEncPrepCfg *set = &ctx->set->prep; + hal_h265e_dbg_input("MPP_ENC_SET_PREP_CFG: change = %d\n", + set->change); + ret = vepu22_check_prep_parameter(set); + ctx->option |= H265E_SET_PREP_CFG; + break; + } + + case MPP_ENC_SET_RC_CFG : { + MppEncRcCfg* rc = (MppEncRcCfg*)&ctx->set->rc; + hal_h265e_dbg_input("MPP_ENC_SET_RC_CFG,change = %d,rc.gop = %d\n", + rc->change, rc->gop); + ret = vepu22_check_rc_cfg_change(ctx, rc); + change = rc->change; + break; + } + + case MPP_ENC_SET_CODEC_CFG : { + MppEncH265Cfg *src = &ctx->set->codec.h265; + vepu22_check_code_cfg_change(ctx, src); + change = ctx->cfg->codec.h265.change; + hal_h265e_dbg_input("MPP_ENC_SET_CODEC_CFG,change = %d\n", change); + break; + } + + case MPP_ENC_SET_CTU_QP: { + hal_h265e_dbg_input("MPP_ENC_SET_CTU_QP\n"); + ret = vepu22_set_ctu(ctx, param); + break; + } + + case MPP_ENC_SET_ROI_CFG: { + hal_h265e_dbg_input("MPP_ENC_SET_ROI_CFG\n"); + ret = vepu22_set_roi(ctx, param); + break; + } + } + hal_h265e_dbg_input("ctx->option = 0x%x H265E_SET_ALL_CFG = 0x%x\n", + ctx->option, H265E_SET_ALL_CFG); + if ((ctx->init == 0) && (ctx->option & H265E_SET_ALL_CFG) == H265E_SET_ALL_CFG) { + ret = vepu22_set_cfg(ctx); + ctx->option = 0; + ctx->init = 1; + } else if (ctx->init == 1) { + if ((hw_cfg->cfg_mask != 0) || (change != 0)) { + vepu22_set_cfg(ctx); + } + } + + hal_h265e_dbg_func("leave hal %p\n", hal); + + return ret; +} + + diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu22.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu22.h new file mode 100644 index 00000000..78218230 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu22.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rk_type.h" + +#ifndef __HAL_H265E_VEPU22_H__ +#define __HAL_H265E_VEPU22_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +MPP_RET hal_h265e_vepu22_init (void *hal, MppHalCfg *cfg); +MPP_RET hal_h265e_vepu22_deinit (void *hal); +MPP_RET hal_h265e_vepu22_gen_regs(void *hal, HalTaskInfo *task); +MPP_RET hal_h265e_vepu22_start (void *hal, HalTaskInfo *task); +MPP_RET hal_h265e_vepu22_wait (void *hal, HalTaskInfo *task); +MPP_RET hal_h265e_vepu22_reset (void *hal); +MPP_RET hal_h265e_vepu22_flush (void *hal); +MPP_RET hal_h265e_vepu22_control (void *hal, RK_S32 cmd_type, void *param); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu22_def.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu22_def.h new file mode 100644 index 00000000..9880408c --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu22_def.h @@ -0,0 +1,1011 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HAL_H265E_VEPU22_DEF_H__ +#define __HAL_H265E_VEPU22_DEF_H__ + +#include "mpp_env.h" +#include "mpp_log.h" +#include "mpp_common.h" +#include "mpp_device.h" +#include "mpp_hal.h" + + +typedef enum { + H265E_LITTLE_ENDIAN, + H265E_BIG_ENDIAN +} H265E_STREAM_ENDIAN; + +#define H265E_MAIN_TILER (0) +#define H265E_MAIN_LEVEL41 (0) +/* +* HEVC Profile enum type +*/ +typedef enum { + H265E_Profile_Unknown = 0x0, + H265E_Profile_Main = 0x1, + H265E_Profile_Main10 = 0x2, + /* + * Main10 profile with HDR SEI support. + */ + H265E_Profile_Main10HDR10 = 0x1000, + H265E_Profile_Max = 0x7FFFFFFF +} H265E_PROFILE_TYPE; + +typedef enum { + H265E_PIC_TYPE_I = 0, + H265E_PIC_TYPE_P = 1, + /* + * not support in H265 Encoder + */ + H265E_PIC_TYPE_B = 2, + H265E_PIC_TYPE_IDR = 3, + H265E_PIC_TYPE_CRA = 4, +} H265E_PIC_TYPE; + +typedef enum { + H265E_SET_CFG_INIT = 0, + H265E_SET_PREP_CFG = 1, + H265E_SET_RC_CFG = 2, + H265E_SET_CODEC_CFG = 4, + H265E_SET_ALL_CFG = (H265E_SET_PREP_CFG | H265E_SET_RC_CFG | H265E_SET_CODEC_CFG) +} H265eCfgOption; + +typedef enum { + H265E_CFG_SEQ_SRC_SIZE_CHANGE = (1 << 0), + H265E_CFG_SEQ_PARAM_CHANGE = (1 << 1), + H265E_CFG_GOP_PARAM_CHANGE = (1 << 2), + H265E_CFG_INTRA_PARAM_CHANGE = (1 << 3), + H265E_CFG_CONF_WIN_TOP_BOT_CHANGE = (1 << 4), + H265E_CFG_CONF_WIN_LEFT_RIGHT_CHANGE = (1 << 5), + H265E_CFG_FRAME_RATE_CHANGE = (1 << 6), + H265E_CFG_INDEPENDENT_SLICE_CHANGE = (1 << 7), + H265E_CFG_DEPENDENT_SLICE_CHANGE = (1 << 8), + H265E_CFG_INTRA_REFRESH_CHANGE = (1 << 9), + H265E_CFG_PARAM_CHANGE = (1 << 10), + H265E_CFG_CHANGE_RESERVED = (1 << 11), + H265E_CFG_RC_PARAM_CHANGE = (1 << 12), + H265E_CFG_RC_MIN_MAX_QP_CHANGE = (1 << 13), + H265E_CFG_RC_TARGET_RATE_LAYER_0_3_CHANGE = (1 << 14), + H265E_CFG_RC_TARGET_RATE_LAYER_4_7_CHANGE = (1 << 15), + H265E_CFG_SET_NUM_UNITS_IN_TICK = (1 << 18), + H265E_CFG_SET_TIME_SCALE = (1 << 19), + H265E_CFG_SET_NUM_TICKS_POC_DIFF_ONE = (1 << 20), + H265E_CFG_RC_TRANS_RATE_CHANGE = (1 << 21), + H265E_CFG_RC_TARGET_RATE_CHANGE = (1 << 22), + H265E_CFG_ROT_PARAM_CHANGE = (1 << 23), + H265E_CFG_NR_PARAM_CHANGE = (1 << 24), + H265E_CFG_NR_WEIGHT_CHANGE = (1 << 25), + H265E_CFG_SET_VCORE_LIMIT = (1 << 27), + H265E_CFG_CHANGE_SET_PARAM_ALL = (0xFFFFFFFF), +} H265eCfgMask; + + +typedef enum { + H265E_SRC_YUV_420 = 0, + + /* + * 3Plane 1.Y, 2.U, 3.V YYYYYYYYY UUUU VVVV + */ + H265E_SRC_YUV_420_YU12 = 0, + + /* + * 3Plane 1.Y, 2.V, 3.U YYYYYYYYYY VVVV UUUU + */ + H265E_SRC_YUV_420_YV12, + + /* + * 2 Plane 1.Y 2. UV YYYYYYYYY UVUVUVUVUVU + */ + H265E_SRC_YUV_420_NV12, + + /* + * 2 Plane 1.Y 2. VU YYYYYYYYY VUVUVUVUVUV + */ + H265E_SRC_YUV_420_NV21, + H265E_SRC_YUV_420_MAX, +} H265E_SRC_FORMAT; + + +typedef enum { + LINEAR_FRAME_MAP = 0, + + /* + * Tiled frame vertical map type + */ + TILED_FRAME_V_MAP = 1, + + /* + * Tiled frame horizontal map type + */ + TILED_FRAME_H_MAP = 2, + + /* + * Tiled mixed field vertical map type + */ + TILED_FIELD_V_MAP = 3, + + /* + * Tiled mixed field vertical map type + */ + TILED_MIXED_V_MAP = 4, + + /* + * Tiled frame horizontal map type + */ + TILED_FRAME_MB_RASTER_MAP = 5, + + /* + * Tiled frame horizontal map type + */ + TILED_FIELD_MB_RASTER_MAP = 6, + + /* + * Tiled frame no bank map. WAVE4 and CODA7L do not support tiledmap type for frame buffer. + */ + TILED_FRAME_NO_BANK_MAP = 7, + + /* + * Tiled field no bank map. WAVE4 and CODA7L do not support tiledmap type for frame buffer. + */ + TILED_FIELD_NO_BANK_MAP = 8, + + /* + * Linear field map type. WAVE4 and CODA7L do not support tiledmap type for frame buffer. + */ + LINEAR_FIELD_MAP = 9, + + CODA_TILED_MAP_TYPE_MAX = 10, + + /* + * Compressed framebuffer type + */ + COMPRESSED_FRAME_MAP = 10, + + /* + * Tiled sub-CTU(32x32) map type - within a sub-CTU, + * the first row of 16x32 is read in vertical direction and then the second row of 16x32 is read. + */ + TILED_SUB_CTU_MAP = 11, + + /* + * AFBC(ARM Frame Buffer Compression) compressed frame map type + */ + ARM_COMPRESSED_FRAME_MAP = 12, + TILED_MAP_TYPE_MAX +} H265E_TiledMapType; + +#define H265E_MAX_NUM_TEMPORAL_LAYER 7 +#define H265E_MAX_GOP_NUM 8 +#define H265E_MIN_PIC_WIDTH 256 +#define H265E_MIN_PIC_HEIGHT 128 +#define H265E_MAX_PIC_WIDTH 1920 +#define H265E_MAX_PIC_HEIGHT 1080 +#define MAX_ROI_NUMBER 64 + +typedef enum { + /* + * gop size and intra period define by custom + */ + PRESET_IDX_CUSTOM_GOP = 0, + + /* + * All Intra, gopsize = 1 + */ + PRESET_IDX_ALL_I = 1, + + /* + * Consecutive P, cyclic gopsize = 1 + */ + PRESET_IDX_IPP = 2, + + /* + * Consecutive P, cyclic gopsize = 4 + */ + PRESET_IDX_IPPPP = 6, +} H265E_GOP_PRESET_IDX; + +typedef enum { + H265E_OPT_COMMON = 0, + H265E_OPT_CUSTOM_GOP = 1, + H265E_OPT_CUSTOM_HEADER = 2, + H265E_OPT_VUI = 3, + H265E_OPT_ALL_PARAM = 0xffffffff +} H265E_SET_PARAM_OPTION; + +typedef enum { + H265E_PARAM_CHANEGED_COMMON = 1, + H265E_PARAM_CHANEGED_CUSTOM_GOP = 2, + H265E_PARAM_CHANEGED_VUI = 4, + H265E_PARAM_CHANEGED_REGISTER_BUFFER = 8 +} H265E_PARAM_CHANEGED; + +/* + * this is a data structure for setting CTU level options (ROI, CTU mode, CTU QP) in HEVC encoder. + */ +typedef struct { + /* + * It enables ROI map. + */ + RK_U32 roi_enable; + + /* + * It specifies the delta QP for ROI important level. + */ + RK_U32 roi_delta_qp; + + /* + * Endianess of ROI CTU map. + */ + RK_U32 map_endian; + /* + * Stride of CTU-level ROI/mode/QP map + * Set this with (Width + CTB_SIZE - 1) / CTB_SIZE + */ + RK_U32 map_stride; + + /* + * It enables CTU QP map that allows CTUs to be encoded with the given QPs. + * NOTE: rc_enable should be turned off for this, encoding with the given CTU QPs. + */ + RK_U32 ctu_qp_enable; +} H265e_CTU; + +typedef struct { + /* + * It enables to encode the prefix SEI NAL which is given by host. + */ + RK_U8 prefix_sei_nal_enable; + + /* + * A flag whether to encode PREFIX_SEI_DATA with a picture of this command or with a source picture of the buffer at the moment + * 0 : encode PREFIX_SEI_DATA when a source picture is encoded. + * 1 : encode PREFIX_SEI_DATA at this command. + */ + RK_U8 prefix_sei_data_order; + + /* enables to encode the suffix SEI NAL which is given by host.*/ + RK_U8 suffix_sei_nal_enable; + + /* + * A flag whether to encode SUFFIX_SEI_DATA with a picture of this command or with a source picture of the buffer at the moment + * 0 : encode SUFFIX_SEI_DATA when a source picture is encoded. + * 1 : encode SUFFIX_SEI_DATA at this command. + */ + RK_U8 suffix_sei_data_enc_order; + + /* + * The total byte size of the prefix SEI + */ + RK_U32 prefix_sei_data_size; + + /* + * The start address of the total prefix SEI NALs to be encoded + */ + RK_U32 prefix_sei_nal_addr; + + /* + * The total byte size of the suffix SEI + */ + RK_U32 suffix_sei_data_size; + + /* + * The start address of the total suffix SEI NALs to be encoded + */ + RK_U32 suffix_sei_nal_addr; +} H265E_SEI; + +/* + * This is a data structure for setting VUI parameters in HEVC encoder. + */ +typedef struct { + /* + * VUI parameter flag + */ + RK_U32 flags; + + /* + * aspect_ratio_idc + */ + RK_U32 aspect_ratio_idc; + + /* + * sar_width, sar_height (only valid when aspect_ratio_idc is equal to 255) + */ + RK_U32 sar_size; + /* + * overscan_appropriate_flag + */ + RK_U32 over_scan_appropriate; + + /* + * VUI parameter flag + */ + RK_U32 signal; + + /* + * chroma_sample_loc_type_top_field, chroma_sample_loc_type_bottom_field + */ + RK_U32 chroma_sample_loc; + + /* + * def_disp_win_left_offset, def_disp_win_right_offset + */ + RK_U32 disp_win_left_right; + + /* + * def_disp_win_top_offset, def_disp_win_bottom_offset + */ + RK_U32 disp_win_top_bottom; +} H265e_VUI; + +/* + * This is a data structure for custom GOP parameters of the given picture. + */ +typedef struct { + /* + * picture type of #th picture in the custom GOP + * the value define in H265E_PIC_TYPE(B frame not support) + */ + RK_U32 type; + + /* + * A POC offset of #th picture in the custom GOP + */ + RK_U32 offset; + + /* + * A quantization parameter of #th picture in the custom GOP + */ + RK_U32 qp; + + /* + * POC offset of reference L0 of #th picture in the custom GOP + */ + RK_U32 ref_poc_l0; + + /* + * POC offset of reference L1 of #th picture in the custom GOP + * Not support B frame in H265 Encoder,so the value of ref_poc_l1 + * is always 0 + */ + RK_U32 ref_poc_l1; + + /* + * A temporal ID of #th picture in the custom GOP + */ + RK_U32 temporal_id; +} H265e_Custom_Gop_PIC; + + +/* + * This is a data structure for custom GOP parameters. + */ +typedef struct { + /* + * size of the custome GOP (the value can be 0~8) + */ + RK_U32 custom_gop_size; + + /* + * It derives a lamda weight internally instead of using lamda weight specified. + */ + RK_U32 use_derive_lambda_weight; + + /* + * Picture parameters of #th picture in the custom GOP + */ + H265e_Custom_Gop_PIC pic[H265E_MAX_GOP_NUM]; + + /* + * A lamda weight of #th picture in the custom GOP + */ + RK_U32 gop_pic_lambda[H265E_MAX_GOP_NUM]; +} H265e_Custom_Gop; + +typedef struct { + /* + * Whether host encode a header implicitly or not. + * If this value is 1, below encode options will be ignored + */ + int implicitHeaderEncode; + + /* + * a flag to encode VCL nal unit explicitly + */ + int encodeVCL; + + /* + * a flag to encode VPS nal unit explicitly + */ + int encodeVPS; + + /* + * a flag to encode SPS nal unit explicitly + */ + int encodeSPS; + + /* + * a flag to encode PPS nal unit explicitly + */ + int encodePPS; + + /* + * a flag to encode AUD nal unit explicitly + */ + int encodeAUD; + + /* + * a flag to encode EOS nal unit explicitly + */ + int encodeEOS; + + /* + * a flag to encode EOB nal unit explicitly + */ + int encodeEOB; + + /* + * a flag to encode VUI nal unit explicitly + */ + int encodeVUI; +} EncCodeOpt; + +typedef struct hal_h265e_cfg { + /* + * A profile indicator + * 1 : main + * 2 : main10 + */ + RK_U8 profile; + + /* + * only support to level 4.1 + */ + RK_U8 level; + + /* + * A tier indicator + * 0 : main + * 1 : high + */ + RK_U8 tier; + + /* + * A chroma format indecator, only support YUV420 + */ + RK_U8 chroma_idc; + + /* + * the source's width and height + */ + RK_U16 width; + RK_U16 height; + + /* + * the source's width stride and height stride + */ + RK_U16 width_stride; + RK_U16 height_stride; + /* + * bitdepth,only support 8 bits(only support 8 bits) + */ + RK_U8 bit_depth; + + /* + * source yuv's format. The value is defined in H265E_FrameBufferFormat(only support YUV420) + * the value could be YU12,YV12,NV12,NV21 + */ + RK_U8 src_format; + + RK_U8 src_endian; + RK_U8 bs_endian; + RK_U8 fb_endian; + RK_U8 frame_rate; + RK_U8 frame_skip; + RK_U32 bit_rate; + + RK_U32 fbc_map_type; + RK_U32 line_buf_int_en; + RK_U32 slice_int_enable; + RK_U32 ring_buffer_enable; + + EncCodeOpt codeOption; + + /* + * value 1:enables lossless coding + */ + RK_S32 lossless_enable; + + /* + * value 1:enables constrained intra prediction + */ + RK_S32 const_intra_pred_flag; + + /* + * The value of chroma(cb) qp offset + */ + RK_S32 chroma_cb_qp_offset; + + /* + * The value of chroma(cr) qp offset + */ + RK_S32 chroma_cr_qp_offset; + + + /* + * A GOP structure option,not support B slice + * 0: Custom GOP + * 1 : I-I-I-I,..I (all intra, gop_size=1) + * 2 : I-P-P-P,...P(consecutive P, gop_size=1) + * 6 : I-P-P-P-P,(consecutive P, gop_size=4) + */ + RK_S32 gop_idx; + + /* + * An intra picture refresh mode + * 0 : Non-IRAP + * 1 : CRA + * 2 : IDR + */ + RK_S32 decoding_refresh_type; + + /* + * A quantization parameter of intra picture + */ + RK_S32 intra_qp; + + /* + * A period of intra picture in GOP size + */ + RK_S32 intra_period; + + /* + * A conformance window size of TOP,BUTTOM,LEFT,RIGHT + */ + RK_U16 conf_win_top; + RK_U16 conf_win_bot; + RK_U16 conf_win_left; + RK_U16 conf_win_right; + + /* + * A slice mode for independent slice + * 0 : no multi-slice + * 1 : Slice in CTU number + * 2 : Slice in number of byte + */ + RK_U32 independ_slice_mode; + /* + * The number of CTU or bytes for a slice when independ_slice_mode is set with 1 or 2. + */ + RK_U32 independ_slice_mode_arg; + /* + * slice mode for dependent slice + * 0 : no multi-slice + * 1 : Slice in CTU number + * 2 : Slice in number of byte + */ + RK_U32 depend_slice_mode; + + /* + * The number of CTU or bytes for a slice when depend_slice_mode is set with 1 or 2. + */ + RK_U32 depend_slice_mode_arg; + + /* + * An intra refresh mode + * 0 : No intra refresh + * 1 : Row + * 2 : Column + * 3 : Step size in CTU + */ + RK_U32 intra_refresh_mode; + + /* + * The number of CTU (only valid when intraRefreshMode is 3.) + */ + RK_U32 intra_refresh_arg; + + /* + * It uses one of the recommended encoder parameter presets. + * 0 : Custom + * 1 : Recommend enc params (slow encoding speed, highest picture quality) + * 2 : Boost mode (normal encoding speed, normal picture quality) + * 3 : Fast mode (high encoding speed, low picture quality) + */ + RK_U8 use_recommend_param; + + /* + * It enables a scaling list + */ + RK_U8 scaling_list_enable; + + /* + * It specifies CU size. + * 3'b001: 8x8 + * 3'b010: 16x16 + * 3'b100 : 32x32 + */ + RK_U8 cu_size_mode; + + /* + * It enables temporal motion vector prediction. + */ + RK_U8 tmvp_enable; + + /* + * It enables wave-front parallel processing. + * This process is not support in H265 Encoder,so the value of it always 0 + */ + RK_U8 wpp_enable; + + /* + * Maximum number of merge candidates (0~2) + */ + RK_U8 max_num_merge; + + /* + * It enables dynamic merge 8x8 candidates. + */ + RK_U8 dynamic_merge_8x8_enable; + + /* + * It enables dynamic merge 16x16 candidates. + */ + RK_U8 dynamic_merge_16x16_enable; + /* + * It enables dynamic merge 32x32 candidates. + */ + RK_U8 dynamic_merge_32x32_enable; + + /* + * It disables in-loop deblocking filtering. + */ + RK_U8 disable_deblk; + + /* + * it enables filtering across slice boundaries for in-loop deblocking. + */ + RK_U8 lf_cross_slice_boundary_enable; + + /* + * BetaOffsetDiv2 for deblocking filter + */ + RK_U8 beta_offset_div2; + + /* + * TcOffsetDiv3 for deblocking filter + */ + RK_U8 tc_offset_div2; + + /* + * It enables transform skip for an intra CU. + */ + RK_U8 skip_intra_trans; + + /* + * It enables SAO (sample adaptive offset). + */ + RK_U8 sao_enable; + + /* + * It enables to make intra CUs in an inter slice. + */ + RK_U8 intra_in_inter_slice_enable; + + /* + * It enables intra NxN PUs. + */ + RK_U8 intra_nxn_enable; + + /* + * specifies intra QP offset relative to inter QP (Only available when rc_enable is enabled) + */ + RK_S8 intra_qp_offset; + + /* + * It specifies encoder initial delay,Only available when RateControl is enabled + * (encoder initial delay = initial_delay * init_buf_levelx8 / 8) + */ + int init_buf_levelx8; + + /* + * specifies picture bits allocation mode. + * Only available when RateControl is enabled and GOP size is larger than 1 + * 0: More referenced pictures have better quality than less referenced pictures + * 1: All pictures in a GOP have similar image quality + * 2: Each picture bits in a GOP is allocated according to FixedRatioN + */ + RK_U8 bit_alloc_mode; + + /* + * A fixed bit ratio (1 ~ 255) for each picture of GOP's bitallocation + * N = 0 ~ (MAX_GOP_SIZE - 1) + * MAX_GOP_SIZE = 8 + * For instance when MAX_GOP_SIZE is 3, FixedBitRaio0 + * to FixedBitRaio2 can be set as 2, 1, and 1 repsectively for + * the fixed bit ratio 2:1:1. This is only valid when BitAllocMode is 2. + */ + RK_U8 fixed_bit_ratio[H265E_MAX_GOP_NUM]; + + /* + * enable rate control + */ + RK_U32 rc_enable; + + /* + * enable CU level rate control + */ + RK_U8 cu_level_rc_enable; + + /* + * enable CU QP adjustment for subjective quality enhancement + */ + RK_U8 hvs_qp_enable; + + /* + * enable QP scaling factor for CU QP adjustment when hvs_qp_enable = 1 + */ + RK_U8 hvs_qp_scale_enable; + + /* + * A QP scaling factor for CU QP adjustment when hvs_qp_enable = 1 + */ + RK_S8 hvs_qp_scale; + + /* + * A minimum QP for rate control + */ + RK_S8 min_qp; + + /* + * A maximum QP for rate control + */ + RK_S8 max_qp; + + /* + * A maximum delta QP for rate control + */ + RK_S8 max_delta_qp; + + /* + * A peak transmission bitrate in bps + */ + RK_U32 trans_rate; + + /* + * It specifies the number of time units of a clock + * operating at the frequency time_scale Hz + */ + RK_U32 num_units_in_tick; + + /* + * It specifies the number of time units that pass in one second + */ + RK_U32 time_scale; + + /* + * It specifies the number of clock ticks corresponding to a + * difference of picture order count values equal to 1 + */ + RK_U32 num_ticks_poc_diff_one; + + /* + * The value of initial QP by host. + * This value is meaningless if INITIAL_RC_QP == 63 + */ + int initial_rc_qp; + + /* + * enables noise reduction algorithm to Y/Cb/Cr component. + */ + RK_U8 nr_y_enable; + RK_U8 nr_cb_enable; + RK_U8 nr_cr_enable; + + /* + * enables noise estimation for reduction. + * When this is disabled, noise estimation is carried out ouside VPU. + */ + RK_U8 nr_noise_est_enable; + /* + * It specifies Y/Cb/Cr noise standard deviation if no use of noise estimation (nr_noise_est_enable=0) + */ + RK_U8 nr_noise_sigma_y; + RK_U8 nr_noise_sigma_cb; + RK_U8 nr_noise_sigma_cr; + + /* A weight to Y noise level for intra picture (0 ~ 31). + * nr_intra_weight_y/4 is multiplied to the noise level that has been estimated. + * This weight is put for intra frame to be filtered more strongly or more weakly than just with the estimated noise level. + */ + RK_U8 nr_intra_weight_y; + + /* + * A weight to Cb noise level for intra picture (0 ~ 31). + */ + RK_U8 nr_intra_weight_cb; + + /* + * A weight to Cr noise level for intra picture (0 ~ 31). + */ + RK_U8 nr_intra_weight_cr; + + /* A weight to Y noise level for inter picture (0 ~ 31). + * nr_inter_weight_y/4 is multiplied to the noise level that has been estimated. + * This weight is put for inter frame to be filtered more strongly or more weakly than just with the estimated noise level. + */ + RK_U8 nr_inter_weight_y; + + /* + * A weight to Cb noise level for inter picture (0 ~ 31). + */ + RK_U8 nr_inter_weight_cb; + + /* + * A weight to Cr noise level for inter picture (0 ~ 31). + */ + RK_U8 nr_inter_weight_cr; + /* + * a minimum QP for intra picture (0 ~ 51). + * It is only available when rc_enable is 1. + */ + RK_U8 intra_min_qp; + + /* + * a maximum QP for intra picture (0 ~ 51). + * It is only available when rc_enable is 1. + */ + RK_U8 intra_max_qp; + + RK_U32 initial_delay; + + RK_U8 hrd_rbsp_in_vps; + RK_U8 hrd_rbsp_in_vui; + RK_U32 vui_rbsp; + + /* + * The size of the HRD rbsp data + */ + RK_U32 hrd_rbsp_data_size; + + /* + * The address of the HRD rbsp data + */ + RK_U32 hrd_rbsp_data_addr; + + /* + * The size of the VUI rbsp data + */ + RK_U32 vui_rbsp_data_size; + + /* + * The address of the VUI rbsp data + */ + RK_U32 vui_rbsp_data_addr; + + RK_U8 use_long_term; + RK_U8 use_cur_as_longterm_pic; + RK_U8 use_longterm_ref; + + H265e_Custom_Gop gop; + H265e_CTU ctu; + H265e_VUI vui; + H265E_SEI sei; + + /* + * define which type of parameters are changed, + * only support common paramter chanegd now,see H265eCommonCfgMask + */ + RK_U32 cfg_option; + + /* + * define which parameters are changed,see H265E_SET_PARAM_OPTION + */ + RK_U32 cfg_mask; +} HalH265eCfg; + + +typedef struct { + /* + * the address of source(yuv) data for encoding + */ + RK_U32 src_addr; + + /* + * the size of source(yuv) data for encoding + */ + RK_U32 src_size; + + /* + * the address of bitstream buffer + */ + RK_U32 bs_addr; + + /* + * the size of bitstream buffer + */ + RK_U32 bs_size; + + /* + * the fd of roi map buffer + */ + RK_U32 roi_fd; + + /* + * the fd of ctu qp buffer + */ + RK_U32 ctu_qp_fd; + + /* + * the flag that stream is end + */ + RK_U32 stream_end; + + /* + * skip current frame + */ + RK_U32 skip_pic; + + /* + * A flag to use a force picture quantization parameter + */ + RK_U32 force_qp_enable; + + /* + * Force picture quantization parameter for I picture + */ + RK_U32 force_qp_I; + + /* + Force picture quantization parameter for P picture + */ + RK_U32 force_qp_P; + + /* + * A flag to use a force picture type + */ + RK_U32 force_frame_type_enable; + + /* + * A force picture type (I, P, IDR, CRA) + */ + RK_U32 force_frame_type; +} EncInfo; + +typedef struct hal_h265e_header { + RK_U32 buf; + RK_U32 size; +} H265E_STREAM_HEAD; + +typedef struct hal_h265e_vepu22_result { + RK_U32 bs_size; + RK_U32 enc_pic_cnt; + RK_U32 pic_type; + RK_U32 num_of_slice; + RK_U32 pick_skipped; + RK_U32 num_intra; + RK_U32 num_merge; + RK_U32 num_skip_block; + RK_U32 avg_ctu_qp; + RK_S32 recon_frame_index; + RK_U32 gop_idx; + RK_U32 poc; + RK_U32 src_idx; + RK_U32 fail_reason; +} H265eVepu22Result; + +#endif diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu22_reg.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu22_reg.h new file mode 100644 index 00000000..29dd20e4 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu22_reg.h @@ -0,0 +1,1188 @@ +/* + * + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __HAL_H265E_VEPU22_REG_H__ +#define __HAL_H265E_VEPU22_REG_H__ + +#include "rk_type.h" + +typedef struct H265e_REGS_t { + // 0x0000 + struct { + RK_U32 debugmode : 1; + RK_U32 reserve0 : 2; + RK_U32 use_po_conf : 1; + RK_U32 reserve1 : 28; + } sw_reg0; + + // 0x0004 Current program counter + struct { + RK_U32 cur_pc; + } sw_reg1; + + // 0x0008 + RK_U32 sw_reg2; + // 0x000c Debugger control + struct { + RK_U32 step_mask_enable : 1; + RK_U32 reserve : 31; + } sw_reg3; + + // 0x0010 Debugger control + struct { + RK_U32 step : 1; + RK_U32 resume : 1; + RK_U32 stable_brk : 1; + RK_U32 imm_brk : 1; + RK_U32 reserve : 28; + } sw_reg4; + + // 0x0014 V-CPU debugger index register + struct { + RK_U32 debug_index : 8; + RK_U32 write_debug : 1; + RK_U32 read_debug : 1; + RK_U32 reserve : 28; + } sw_reg5; + + // 0x0018 V-CPU debugger write data register + struct { + RK_U32 write_data_debug; + } sw_reg6; + + // 0x001c V-CPU debugger read data register + struct { + RK_U32 read_data_debug; + } sw_reg7; + + // 0x0020 FIO CRTL, READY + struct { + RK_U32 fio_addr : 16; + RK_U32 rw_flag : 1; + RK_U32 reserve : 14; + RK_U32 ready : 1; + } sw_reg8; + + // 0x0024 FIO data + struct { + RK_U32 fio_data; + } sw_reg9; + + // 0x0028 + RK_U32 sw_reg10; + + // 0x002c + RK_U32 sw_reg11; + + // 0x0030 interrupt status + struct { + RK_U32 init_vpu : 1; + RK_U32 dec_pic_hdr : 1; + RK_U32 fini_seq : 1; + RK_U32 dec_pic : 1; + RK_U32 set_framebuf : 1; + RK_U32 flush_decoder : 1; + RK_U32 reserve0 : 2; + RK_U32 get_fw_version : 1; + RK_U32 query_decoder : 1; + RK_U32 sleep_vpu : 1; + RK_U32 wakeup_vpu : 1; + RK_U32 change_inst : 1; + RK_U32 reserve1 : 1; + RK_U32 create_inst : 1; + RK_U32 bitstream_empty : 1; + RK_U32 reserve2 : 16; + } sw_reg12; + + // 0x0034 interrupt reason clear + struct { + RK_U32 init_vpu_clr : 1; + RK_U32 dec_pic_hdr_clr : 1; + RK_U32 fini_seq_clr : 1; + RK_U32 dec_pic_clr : 1; + RK_U32 set_framebuf_clr : 1; + RK_U32 flush_decoder_clr : 1; + RK_U32 reserve0 : 2; + RK_U32 get_fw_version_clr : 1; + RK_U32 query_decoder_clr : 1; + RK_U32 sleep_vpu_clr : 1; + RK_U32 wakeup_vpu_clr : 1; + RK_U32 change_inst_clr : 1; + RK_U32 reserve1 : 1; + RK_U32 create_inst_clr : 1; + RK_U32 bitstream_empty_clr : 1; + RK_U32 reserve2 : 16; + } sw_reg13; + + // 0x0038 send host interrupt cmd to vpu + struct { + RK_U32 host_int : 1; + RK_U32 reserve : 31; + } sw_reg14; + + // 0x003c vpu interrupt clear + struct { + RK_U32 vpu_int_clr : 1; + RK_U32 reserve : 31; + } sw_reg15; + + // 0x0040 host interrupt clear + struct { + RK_U32 host_int_clr : 1; + RK_U32 reserve : 31; + } sw_reg16; + + // 0x0044 VPU Interrupt status + struct { + RK_U32 vpu_int_sts : 1; + RK_U32 reserve : 31; + } sw_reg17; + + // 0x0048 Interrupt Enable + struct { + RK_U32 init_vpu_enable : 1; + RK_U32 dec_pic_hdr_enable : 1; + RK_U32 fini_seq_enable : 1; + RK_U32 dec_pic_enable : 1; + RK_U32 set_framebuf_enable : 1; + RK_U32 flush_decoder_enable : 1; + RK_U32 reserve0 : 2; + RK_U32 get_fw_version_enable : 1; + RK_U32 query_decoder_enable : 1; + RK_U32 sleep_vpu_enable : 1; + RK_U32 wakeup_vpu_enable : 1; + RK_U32 change_inst_enable : 1; + RK_U32 reserve1 : 1; + RK_U32 create_inst_enable : 1; + RK_U32 update_bitstream_enable : 1; + RK_U32 reserve2 : 16; + } sw_reg18; + + // 0x004c VPU Interrupt Reason + struct { + RK_U32 init_vpu_done : 1; + RK_U32 dec_pic_hdr_done : 1; + RK_U32 fini_seq_done : 1; + RK_U32 dec_pic_done : 1; + RK_U32 set_framebuf_done : 1; + RK_U32 flush_decoder_done : 1; + RK_U32 reserve0 : 2; + RK_U32 get_fw_version_done : 1; + RK_U32 query_decoder_done : 1; + RK_U32 sleep_vpu_done : 1; + RK_U32 wakeup_vpu_done : 1; + RK_U32 change_inst_done : 1; + RK_U32 reserve1 : 1; + RK_U32 create_inst_done : 1; + RK_U32 bitstream_enmpty : 1; + RK_U32 reserve2 : 16; + } sw_reg19; + + // 0x0050 VPU reset request + struct { + RK_U32 crst_req : 8; + RK_U32 brst_req : 8; + RK_U32 arst_req : 8; + RK_U32 varst_req : 1; + RK_U32 vrst_req : 1; + RK_U32 mrst_req : 1; + RK_U32 reserve : 5; + } sw_reg20; + + // 0x0054 VPU reset status + struct { + RK_U32 crst_sts : 8; + RK_U32 brst_sts : 8; + RK_U32 arst_sts : 8; + RK_U32 varst_sts : 1; + RK_U32 vrst_sts : 1; + RK_U32 mrst_sts : 1; + RK_U32 reserve : 5; + } sw_reg21; + + // 0x0058 V-CPU restart request + struct { + RK_U32 vcpu_restart : 1; + RK_U32 reserve : 31; + } sw_reg22; + + // 0x005c Clock gating control register + struct { + RK_U32 cclk_en : 8; + RK_U32 bclk_en : 8; + RK_U32 aclk_en : 8; + RK_U32 aclk_cpu_en : 1; + RK_U32 cvclk_en : 1; + RK_U32 mclk_en : 1; + RK_U32 reserve : 5; + } sw_reg23; + + // 0x0060 VPU remaps addresses + struct { + RK_U32 remap_size : 9; + RK_U32 remap_berr : 1; + RK_U32 remap_attr : 1; + RK_U32 remap_parse_size_en : 1; + RK_U32 remap_idx : 4; + RK_U32 endian : 4; + RK_U32 axiid_porc : 4; + RK_U32 reserve : 7; + RK_U32 remap_globen : 1; + } sw_reg24; + + // 0x0064 Remap region base address in virtual address space + struct { + RK_U32 reserve : 12; + RK_U32 vpu_remap_vaddr : 20; + } sw_reg25; + + // 0x0068 Remap region base address in phys address space + struct { + RK_U32 reserve : 12; + RK_U32 vpu_remap_paddr : 20; + } sw_reg26; + + // 0x006c VPU Start Request + struct { + RK_U32 vpu_remap_core_start : 1; + RK_U32 reserve : 31; + } sw_reg27; + + // 0x0070 VPU Busy Status + struct { + RK_U32 vpu_busy_status : 1; + RK_U32 reserve : 31; + } sw_reg28; + + // 0x0074 Reserved for Report VPU status + struct { + RK_U32 vpu_halt_status : 5; + RK_U32 reserve : 27; + } sw_reg29; + + // 0x0078 Reserved for VPU status reproting + struct { + RK_U32 vpu_core_parse_status : 1; + RK_U32 reserve : 31; + } sw_reg30; + + // 0x007c Reserved for VPU status reproting + struct { + RK_U32 vpu_vcore_dec_status : 1; + RK_U32 reserve : 31; + } sw_reg31; + + + // 0x0080~0x00fc + RK_U32 sw_reg32_63[32]; + + // 0x0100 Command to run + struct { + RK_U32 command; + } sw_reg64; + + // 0x0104 + struct { + RK_U32 vcore_index : 16; + RK_U32 reserve : 16; + } sw_reg65; + + // 0x0108 + struct { + RK_U32 inst_index : 16; + RK_U32 codec_std : 16; + } sw_reg66; + + // 0x010c + union { + struct { + RK_U32 set_param_option : 2; + RK_U32 reserve : 30; + }; + + RK_U32 init_option; + + struct { + RK_U32 sfb_option : 3; + RK_U32 setup_start : 1; + RK_U32 setup_done : 1; + RK_U32 reserve0 : 11; + RK_U32 fb_endian : 4; + RK_U32 fbc_mode : 6; + RK_U32 reserve1 : 6; + }; + } sw_reg67; + + // 0x0110 + struct { + RK_U32 run_cmd_status : 2; + RK_U32 reserve : 30; + } sw_reg68; + + // 0x0114 + struct { + RK_U32 fail_reason : 32; + } sw_reg69; + + // 0x0118 + union { + struct { + RK_U32 reserve : 12; + RK_U32 code_buf_base : 20; // aligned to 4KB range + }; + + RK_U32 ret_fw_version; + } sw_reg70; + + // 0x011c + union { + struct { + RK_U32 hw_name : 4; + RK_U32 reserve : 28; + }; + + RK_U32 code_size; // aligned to 4KB range + } sw_reg71; + + // 0x0120 + union { + struct { + RK_U32 hw_version : 4; + RK_U32 reserve0 : 28; + }; + + struct { + RK_U32 reserve1 : 4; + RK_U32 bs_start_addr : 28; + }; + + struct { + RK_U32 dpb_stride : 16; + RK_U32 dpb_cbcr_interleave : 1; + RK_U32 dpb_color_format : 3; + RK_U32 bwb_output_format : 3; + RK_U32 wtl_align_mode : 1; + RK_U32 axi_id : 4; + RK_U32 wtl_enable : 1; + RK_U32 nv21_enable : 1; + RK_U32 reserve2 : 2; + }; + + struct { + RK_U32 code_endian : 4; + RK_U32 code_axiid : 4; + RK_U32 reserve3 : 24; + }; + } sw_reg72; + + // 0x0124 + union { + struct { + RK_U32 dpb_height : 16; + RK_U32 dpb_width : 16; + }; + + struct { + RK_U32 reserve0 : 4; + RK_U32 bs_buf_size : 28; // aligned 128bit/16byte + }; + + struct { + RK_U32 use_debug : 1; + RK_U32 cache_disable : 1; + RK_U32 reserve1 : 6; + RK_U32 uart_option : 4; + RK_U32 reserve2 : 20; + }; + + RK_U32 ret_cur_sp; + + RK_U32 cur_sp; + } sw_reg73; + + // 0x0128 + union { + struct { + RK_U32 fb_num_end : 5; + RK_U32 reserve0 : 3; + RK_U32 fb_num_start : 5; + RK_U32 reserve1 : 19; + }; + + struct { + RK_U32 bs_endian : 4; + RK_U32 bs_wrap_around_flag : 1; + RK_U32 bs_slice_wr_ptr_interrupt_flag : 1; + RK_U32 reserve2 : 26; + }; + } sw_reg74; + + + // 0x012c + union { + RK_U32 codec_std; + struct { + RK_U32 explict_end : 1; + RK_U32 stream_end : 1; + RK_U32 reserve0 : 30; + }; + } sw_reg75; + + // 0x0130 + union { + RK_U32 rd_ptr; + RK_U32 hw_date; + } sw_reg76; + + // 0x0134 + union { + RK_U32 time_out_cnt; + RK_U32 wr_ptr; + RK_U32 hw_revision; + } sw_reg77; + + // 0x0138 + struct { + RK_U32 work_buf_base; + } sw_reg78; + + // 0x013c + union { + struct { + RK_U32 gop_work_buf_size : 9; + RK_U32 reserve0 : 23; + } ; + + RK_U32 common_work_buf_size; + } sw_reg79; + + // 0x0140 + struct { + RK_U32 work_buf_endian : 4; + RK_U32 reserve0 : 28; + } sw_reg80; + + // 0x0144 + struct { + RK_U32 temp_buf_base; + } sw_reg81; + + // 0x0148 + struct { + RK_U32 temp_buf_size; + } sw_reg82; + + // 0x014c + struct { + RK_U32 temp_buf_endian : 4; + RK_U32 reserve0 : 28; + } sw_reg83; + + // 0x0150 + struct { + RK_U32 sec_axi_base; + } sw_reg84; + + // 0x0154 + union { + RK_U32 sec_axi_mem_size; + struct { + RK_U32 fbc_c_stride : 16; + RK_U32 fbc_y_stride : 16; + } ; + } sw_reg85; + + // 0x0158 + union { + struct { + RK_U32 reserve0 : 11; + RK_U32 sec_axi_rdo_enable : 1; + RK_U32 reserve1 : 3; + RK_U32 sec_axi_lf_row : 1; + RK_U32 reserve2 : 16; + } ; + + RK_U32 addr_sub_sampled_fb; + } sw_reg86; + + // 0x015c + union { + struct { + RK_U32 custom_gop_param_en : 1; + RK_U32 custom_gop_pic_param_0_en : 1; + RK_U32 custom_gop_pic_param_1_en : 1; + RK_U32 custom_gop_pic_param_2_en : 1; + RK_U32 custom_gop_pic_param_3_en : 1; + RK_U32 custom_gop_pic_param_4_en : 1; + RK_U32 custom_gop_pic_param_5_en : 1; + RK_U32 custom_gop_pic_param_6_en : 1; + RK_U32 custom_gop_pic_param_7_en : 1; + RK_U32 reserve0 : 1; + RK_U32 custom_gop_pic_lambda_0_en : 1; + RK_U32 custom_gop_pic_lambda_1_en : 1; + RK_U32 custom_gop_pic_lambda_2_en : 1; + RK_U32 custom_gop_pic_lambda_3_en : 1; + RK_U32 custom_gop_pic_lambda_4_en : 1; + RK_U32 custom_gop_pic_lambda_5_en : 1; + RK_U32 custom_gop_pic_lambda_6_en : 1; + RK_U32 custom_gop_pic_lambda_7_en : 1; + RK_U32 reserve1 : 14; + } ; + + struct { + RK_U32 neutral_chroma_indication_flag : 1; + RK_U32 reserve2 : 2; + RK_U32 aspect_ratio_info_present_flag : 1; + RK_U32 oversacn_info_present_flag : 1; + RK_U32 video_signal_type_present_flag : 1; + RK_U32 colour_description_present_flag : 1; + RK_U32 chroma_loc_info_present_flag : 1; + RK_U32 default_display_window_flag : 1; + RK_U32 bitstream_restriction_flag : 1; + RK_U32 reserve3 : 22; + } ; + + RK_U32 sub_sampled_one_fb_size; + + RK_U32 addr_report_base; + + struct { + RK_U32 enable_set_seq_src_size : 1; + RK_U32 enable_set_seq_param : 1; + RK_U32 enable_set_seq_gop_param : 1; + RK_U32 enable_set_seq_intra_param : 1; + RK_U32 enable_set_seq_conf_win_top_bot : 1; + RK_U32 enable_set_seq_conf_win_left_right : 1; + RK_U32 enable_set_seq_frame_rate : 1; + RK_U32 enable_set_seq_independent_slice : 1; + RK_U32 enable_set_seq_dependent_slice : 1; + RK_U32 enable_set_seq_intra_refresh : 1; + RK_U32 enable_set_enc_param : 1; + RK_U32 reserve4 : 1; + RK_U32 enable_set_rc_param : 1; + RK_U32 enable_set_rc_min_max_qp : 1; + RK_U32 enable_set_rc_bit_ratio_layer_0_3 : 1; + RK_U32 enable_set_rc_bit_ratio_layer_4_7 : 1; + RK_U32 reserve5 : 2; + RK_U32 enable_set_num_units_in_tick : 1; + RK_U32 enable_set_time_scale : 1; + RK_U32 enable_set_num_ticks_poc_diff_one : 1; + RK_U32 enable_set_num_rc_trans_rate : 1; + RK_U32 enable_set_num_rc_target_rate : 1; + RK_U32 reserve6 : 2; + RK_U32 enable_set_nr_param : 1; + RK_U32 enable_set_nr_weight : 1; + RK_U32 reserve7 : 5; + } ; + } sw_reg87; + + // 0x0160 + union { + RK_U32 report_size; + RK_U32 aspect_ratio_idc; + RK_U32 luma_base0; + + struct { + RK_U32 src_width : 16; + RK_U32 src_height : 16; + } ; + + struct { + RK_U32 custom_gop_size : 4; + RK_U32 drive_lambda_weight : 1; + RK_U32 reserve : 27; + } ; + } sw_reg88; + + // 0x0164 + union { + struct { + RK_U32 sar_width : 16; + RK_U32 sar_height : 16; + } ; + + struct { + RK_U32 pic_type : 2; + RK_U32 poc_offset : 4; + RK_U32 pic_qp : 6; + RK_U32 reserve0 : 2; + RK_U32 ref_poc_l0 : 5; + RK_U32 ref_poc_l1 : 5; + RK_U32 temporal_id : 4; + RK_U32 reserve1 : 4; + } ; + + RK_U32 report_param; + RK_U32 cb_base0; + } sw_reg89; + + // 0x0168 + union { + struct { + RK_U32 implicitly_header_encoder : 1; + RK_U32 vcl : 1; + RK_U32 vps : 1; + RK_U32 sps : 1; + RK_U32 pps : 1; + RK_U32 aud : 1; + RK_U32 eos : 1; + RK_U32 eob : 1; + RK_U32 sei : 1; + RK_U32 vui : 1; + RK_U32 reserve0 : 22; + } ; + + RK_U32 cr_base0; + RK_U32 fbc_luma_offset_base0; + struct { + RK_U32 pic_type : 2; + RK_U32 poc_offset : 4; + RK_U32 pic_qp : 6; + RK_U32 reserve1 : 2; + RK_U32 ref_poc_l0 : 5; + RK_U32 ref_poc_l1 : 5; + RK_U32 reserve2 : 4; + } ; + + RK_U32 overscan_approriate_flag; + } sw_reg90; + + // 0x016c + union { + struct { + RK_U32 pic_type : 2; + RK_U32 poc_offset : 4; + RK_U32 pic_qp : 6; + RK_U32 reserve0 : 2; + RK_U32 ref_poc_l0 : 5; + RK_U32 ref_poc_l1 : 5; + RK_U32 temporal_id : 4; + RK_U32 reserve1 : 4; + } ; + + struct { + RK_U32 pic_skip_flag : 1; + RK_U32 use_force_pic_qp : 1; + RK_U32 force_pic_qp_i : 6; + RK_U32 force_pic_qp_p : 6; + RK_U32 force_pic_qp_b : 6; + RK_U32 use_force_pic_type : 1; + RK_U32 forece_pic_type : 3; + RK_U32 reserve2 : 5; + RK_U32 force_src_pic_qp_flag : 1; + RK_U32 force_src_pic_type_flag : 1; + RK_U32 reserve3 : 1; + } ; + + RK_U32 fbc_chroma_offset_base0; + + struct { + RK_U32 video_format : 3; + RK_U32 video_full_range_flag : 1; + RK_U32 colour_primaries : 8; + RK_U32 transfer_characteristics : 8; + RK_U32 maxtrix_coeffs : 8; + RK_U32 reserve4 : 4; + } ; + + struct { + RK_U32 profile_idc : 3; + RK_U32 level_idc : 9; + RK_U32 tier_idc : 2; + RK_U32 bit_depth : 4; + RK_U32 chroma_format_idc : 2; + RK_U32 use_lossless_coding : 1; + RK_U32 constrained_intra_pred : 1; + RK_U32 chroma_cb_qp_offset : 5; + RK_U32 chroma_cr_qp_offset : 5; + } ; + } sw_reg91; + + // 0x0170 + union { + RK_U32 src_idx; + struct { + RK_U32 gop_preset_idx : 8; + RK_U32 reserve0 : 24; + } ; + + RK_U32 luma_base1; + + struct { + RK_U32 pic_type : 2; + RK_U32 poc_offset : 4; + RK_U32 pic_qp : 6; + RK_U32 reserve1 : 2; + RK_U32 ref_poc_l0 : 5; + RK_U32 ref_poc_l1 : 5; + RK_U32 temporal_id : 4; + RK_U32 reserve2 : 4; + } ; + + struct { + RK_U32 chroma_sample_loc_type_top_field : 16; + RK_U32 chroma_sample_loc_type_bottom_field : 16; + } ; + } sw_reg92; + + // 0x0174 + union { + struct { + RK_U32 pic_type : 2; + RK_U32 poc_offset : 4; + RK_U32 pic_qp : 6; + RK_U32 reserve0 : 2; + RK_U32 ref_poc_l0 : 5; + RK_U32 ref_poc_l1 : 5; + RK_U32 temporal_id : 4; + RK_U32 reserve1 : 4; + } ; + + struct { + RK_U32 def_disp_win_left_offset : 16; + RK_U32 def_disp_win_right_offset : 16; + } ; + + RK_U32 cb_base1; + RK_U32 src_addr_y; + + struct { + RK_U32 decoding_refresh_type : 3; + RK_U32 intra_qp : 6; + RK_U32 reserve3 : 7; + RK_U32 intra_period : 16; + } ; + } sw_reg93; + + // 0x0178 + union { + struct { + RK_U32 pic_type : 2; + RK_U32 poc_offset : 4; + RK_U32 pic_qp : 6; + RK_U32 reserve0 : 2; + RK_U32 ref_poc_l0 : 5; + RK_U32 ref_poc_l1 : 5; + RK_U32 temporal_id : 4; + RK_U32 reserve1 : 4; + } ; + + struct { + RK_U32 conformace_window_size_top : 16; + RK_U32 conformace_window_size_bottom : 16; + } ; + + struct { + RK_U32 def_disp_win_top_offset : 16; + RK_U32 def_disp_win_bottom_offset : 16; + } ; + + RK_U32 cr_base1; + RK_U32 fbc_luma_offset_base1; + RK_U32 src_addr_u; + } sw_reg94; + + // 0x017c + union { + struct { + RK_U32 pic_type : 2; + RK_U32 poc_offset : 4; + RK_U32 pic_qp : 6; + RK_U32 reserve0 : 2; + RK_U32 ref_poc_l0 : 5; + RK_U32 ref_poc_l1 : 5; + RK_U32 temporal_id : 4; + RK_U32 reserve1 : 4; + } ; + + struct { + RK_U32 conformace_window_size_left : 16; + RK_U32 conformace_window_size_right : 16; + } ; + + RK_U32 fbc_chroma_offset_base1; + RK_U32 src_addr_v; + } sw_reg95; + + // 0x0180 + union { + RK_U32 frame_rate_idc; + // A picture type of 7th picture in the custom GOP + struct { + RK_U32 pic_type : 2; + RK_U32 poc_offset : 4; + RK_U32 pic_qp : 6; + RK_U32 reserve0 : 2; + RK_U32 ref_poc_l0 : 5; + RK_U32 ref_poc_l1 : 5; + RK_U32 temporal_id : 4; + RK_U32 reserve1 : 4; + } ; + + struct { + RK_U32 src_c_stride : 16; + RK_U32 src_y_stride : 16; + } ; + + RK_U32 luma_base2; + } sw_reg96; + + // 0x0184 + union { + struct { + RK_U32 src_frame_format : 3; + RK_U32 src_pixel_format : 3; + RK_U32 src_endian : 4; + RK_U32 reserve2 : 22; + } ; + + RK_U32 cb_base2; + + struct { + RK_U32 slice_mode : 3; + RK_U32 reserve : 13; + RK_U32 argument : 16; + } ; + } sw_reg97; + + + // 0x0188 + union { + RK_U32 lambda_weigth; + RK_U32 cr_base2; + + struct { + RK_U32 slice_mode : 3; + RK_U32 reserve : 13; + RK_U32 argument : 16; + } ; + + RK_U32 prefix_se_nal_data_addr; + } sw_reg98; + + // 0x018c + union { + RK_U32 fbc_chroma_offset_base2; + + struct { + RK_U32 prefix_sei_nal_data_enble_flag : 1; + RK_U32 prefix_sei_nal_timing_flag : 1; + RK_U32 reserve0 : 14; + RK_U32 prefix_sei_nal_data_size : 16; + } ; + + RK_U32 lambda_weight; + + struct { + RK_U32 intra_refresh_mode : 3; + RK_U32 reserve1 : 13; + RK_U32 intra_refresh_argument : 16; + } ; + } sw_reg99; + + // 0x0190 + union { + RK_U32 lambda_weight; + RK_U32 luma_base3; + RK_U32 sufffix_sei_nal_data_addr : 1; + struct { + RK_U32 use_recommend_enc_param : 2; + RK_U32 enable_ctu_qp_map : 1; + RK_U32 use_scaling_list : 1; + RK_U32 use_cu_size : 3; + RK_U32 use_tmvp : 1; + RK_U32 reserve0 : 1; + RK_U32 max_num_merge : 3; + RK_U32 use_dynamic_merge_8x8 : 1; + RK_U32 use_dynamic_merge_16x16 : 1; + RK_U32 use_dynamic_merge_32x32 : 1; + RK_U32 disable_dbk : 1; + RK_U32 use_lf_cross_slice_boundary : 1; + RK_U32 beta_offset_div2 : 4; + RK_U32 tc_offset_div2 : 4; + RK_U32 reserve1 : 2; + RK_U32 use_intra_in_inter_slice : 1; + RK_U32 reserve2 : 4; + } ; + + RK_U32 src_timestamp_low; + } sw_reg100; + + // 0x0194 + union { + RK_U32 cb_base_fbc_cbcr_base3; + struct { + RK_U32 suffix_sei_nal_data_enable_flag : 1; + RK_U32 suffix_sei_timing_flag : 1; + RK_U32 reserve0 : 14; + RK_U32 suffix_sei_nal_data_size : 16; + } ; + + RK_U32 src_timestamp_high; + RK_U32 lamba_weight; + } sw_reg101; + + // 0x0198 + union { + struct { + RK_U32 en_rate_control : 1; + RK_U32 en_cu_level_rc : 1; + RK_U32 en_hvs_qp : 1; + RK_U32 en_hvs_qp_scale : 1; + RK_U32 hvs_qp_scale : 3; + RK_U32 bit_alloc_mode : 2; + RK_U32 init_buf_levelx8 : 4; + RK_U32 en_seq_roi : 1; + RK_U32 initial_rc_qp : 6; + RK_U32 initial_delay : 12; + } ; + + RK_U32 lamba_weight; + RK_U32 cr_base_fbc_y_offset_base3; + + struct { + RK_U32 use_src_longterm_pic : 1; + RK_U32 use_ref_longterm_pic : 1; + RK_U32 reserve0 : 14; + RK_U32 ref_longterm_pic_poc : 16; + } ; + } sw_reg102; + + // 0x019c + union { + RK_U32 fbc_chroma_offset_base3; + + struct { + RK_U32 min_qp : 6; + RK_U32 max_qp : 6; + RK_U32 max_delta_qp : 6; + RK_U32 intra_qp_offset : 14; + } ; + + RK_U32 lambda_weight; + } sw_reg103; + + // 0x01a0 + union { + RK_U32 lambda_weight; + + struct { + RK_U32 fixed_bit_ratio_0 : 8; + RK_U32 fixed_bit_ratio_1 : 8; + RK_U32 fixed_bit_ratio_2 : 8; + RK_U32 fixed_bit_ratio_3 : 8; + } ; + + RK_U32 luma_base4; + + struct { + RK_U32 roi_enable_flag : 1; + RK_U32 roi_delta_qp : 7; + RK_U32 ctu_mode_enbale_flag : 1; + RK_U32 ctu_qp_map_enbale_flag : 1; + RK_U32 reserve0 : 2; + RK_U32 ctu_map_endian : 4; + RK_U32 ctu_map_stride : 16; + } ; + } sw_reg104; + + // 0x01a4 + union { + RK_U32 lambda_weight; + RK_U32 roi_map_addr; + RK_U32 cb_base_fbc_cbcr_base4; + struct { + RK_U32 fixed_bit_ratio_4 : 8; + RK_U32 fixed_bit_ratio_5 : 8; + RK_U32 fixed_bit_ratio_6 : 8; + RK_U32 fixed_bit_ratio_7 : 8; + } ; + } sw_reg105; + + // 0x01a8 + union { + RK_U32 cr_base_fbc_y_offset_base4; + struct { + RK_U32 reserve0 : 24; + RK_U32 pic_idx : 8; + } ; + + struct { + RK_U32 enable_nr_y : 1; + RK_U32 enable_nr_cb : 1; + RK_U32 enable_nr_cr : 1; + RK_U32 enable_nr_est_noise : 1; + RK_U32 enable_noise_sigma_y : 7; + RK_U32 enable_noise_sigma_cb : 7; + RK_U32 enable_noise_sigma_cr : 7; + RK_U32 reserve1 : 7; + } ; + + RK_U32 ctu_mode_map_addr; + } sw_reg106; + + // 0x01ac + union { + RK_U32 ctu_qp_map_addr; + RK_U32 fbc_chroma_offset_base4; + struct { + RK_U32 pic_indep_slice_num : 16; + RK_U32 pic_dep_slice_num : 16; + } ; + + struct { + RK_U32 nr_intra_weight_y : 5; + RK_U32 nr_intra_weight_cb : 5; + RK_U32 nr_intra_weight_cr : 5; + RK_U32 nr_inter_weight_y : 5; + RK_U32 nr_inter_weight_cb : 5; + RK_U32 nr_inter_weight_cr : 5; + RK_U32 reserve0 : 2; + } ; + } sw_reg107; + + // 0x01b0 + union { + struct { + RK_U32 reserve0 : 1; + RK_U32 pic_skip : 7; + RK_U32 reserve1 : 24; + } ; + RK_U32 luma_base5; + RK_U32 num_units_in_tick; + } sw_reg108; + + // 0x01b4 + union { + RK_U32 time_scale; + RK_U32 cb_base_fbc_cbcr_base5; + RK_U32 pic_num_intra; + } sw_reg109; + + // 0x01b8 + union { + RK_U32 num_ticks_poc_diff_one; + RK_U32 pic_num_merge; + RK_U32 pic_num_intra; + RK_U32 cr_base_fbc_y_offset_base5; + } sw_reg110; + + // 0x01bc + union { + RK_U32 fbc_chroma_offset_base5; + RK_U32 trans_rate; + } sw_reg111; + + // 0x01c0 + union { + RK_U32 luma_base6; + RK_U32 traget_rate; + RK_U32 pic_num_skip; + } sw_reg112; + + // 0x01c4 + union { + RK_U32 cb_base_fbc_y_offset_base6; + RK_U32 pic_avg_cu_qp; + } sw_reg113; + + // 0x01c8 + union { + RK_U32 cr_base_fbc_y_offset_base6; + RK_U32 pic_byte; + RK_U32 cr_base_fbc_y_base6; + } sw_reg114; + + // 0x01cc + union { + RK_U32 gop_pic_idx; + RK_U32 min_fb_num; + RK_U32 fbc_chroma_offset_base6; + } sw_reg115; + + // 0x01d0 + union { + RK_U32 pic_poc; + RK_U32 nal_info_to_be_encoded; + RK_U32 luma_base7; + } sw_reg116; + + // 0x01d4 + union { + RK_U32 cb_base_fbc_cbcr_base7; + RK_U32 frame_cycle; + } sw_reg117; + + // 0x01d8 + union { + RK_U32 cr_base_fbc_y_offset_base7; + RK_U32 used_src_pic_idx; + RK_U32 ret_min_sec_buf_num; + } sw_reg118; + + // 0x01dc + union { + RK_U32 pic_num; + RK_U32 fbc_chroma_offset_base7; + } sw_reg119; + + // 0x01e0 + union { + RK_U32 col_mv_buf_base0; + struct { + RK_U32 pic_type : 16; + RK_U32 reserve0 : 16; + } ; + } sw_reg120; + + // 0x01e4 + struct { + RK_U32 col_mv_buf_base1; + } sw_reg121; + + // 0x01e8 + struct { + RK_U32 col_mv_buf_base2; + } sw_reg122; + + // 0x01ec + struct { + RK_U32 col_mv_buf_base3; + } sw_reg123; + + // 0x01f0 + struct { + RK_U32 col_mv_buf_base4; + } sw_reg124; + + // 0x01f4 + struct { + RK_U32 col_mv_buf_base5; + } sw_reg125; + + // 0x01f8 + struct { + RK_U32 col_mv_buf_base6; + } sw_reg126; + + // 0x01fc + struct { + RK_U32 col_mv_buf_base7; + } sw_reg127; +} H265eVepu22Regs; +#endif diff --git a/mpp/legacy/vpu_api_legacy.cpp b/mpp/legacy/vpu_api_legacy.cpp index 8cbfc04c..ab6f02ff 100644 --- a/mpp/legacy/vpu_api_legacy.cpp +++ b/mpp/legacy/vpu_api_legacy.cpp @@ -102,7 +102,8 @@ static MPP_RET vpu_api_set_enc_cfg(MppCtx mpp_ctx, MppApi *mpi, RK_S32 gop = (cfg->intraPicRate) ? (cfg->intraPicRate) : (fps_out); RK_S32 qp_init = (coding == MPP_VIDEO_CodingAVC) ? (26) : (coding == MPP_VIDEO_CodingMJPEG) ? (10) : - (coding == MPP_VIDEO_CodingVP8) ? (56) : (0); + (coding == MPP_VIDEO_CodingVP8) ? (56) : + (coding == MPP_VIDEO_CodingHEVC) ? (26) : (0); RK_S32 qp = (cfg->qp) ? (cfg->qp) : (qp_init); RK_S32 profile = cfg->profileIdc; RK_S32 level = cfg->levelIdc; @@ -198,8 +199,11 @@ static MPP_RET vpu_api_set_enc_cfg(MppCtx mpp_ctx, MppApi *mpi, codec_cfg->jpeg.change = MPP_ENC_JPEG_CFG_CHANGE_QP; codec_cfg->jpeg.quant = qp; } break; + case MPP_VIDEO_CodingHEVC : { + codec_cfg->h265.change = MPP_ENC_H265_CFG_INTRA_QP_CHANGE; + codec_cfg->h265.intra_qp = qp; + } break; case MPP_VIDEO_CodingVP8 : - case MPP_VIDEO_CodingHEVC : default : { mpp_err_f("support encoder coding type %d\n", coding); } break; @@ -1391,6 +1395,18 @@ RK_S32 VpuApiLegacy::control(VpuCodecContext *ctx, VPU_API_CMD cmd, void *param) case VPU_API_SET_IMMEDIATE_OUT: { mpicmd = MPP_DEC_SET_IMMEDIATE_OUT; } break; + case VPU_API_ENC_SET_VEPU22_CFG: { + mpicmd = MPP_ENC_SET_CODEC_CFG; + } break; + case VPU_API_ENC_GET_VEPU22_CFG: { + mpicmd = MPP_ENC_GET_CODEC_CFG; + } break; + case VPU_API_ENC_SET_VEPU22_CTU_QP: { + mpicmd = MPP_ENC_SET_CTU_QP; + } break; + case VPU_API_ENC_SET_VEPU22_ROI: { + mpicmd = MPP_ENC_SET_ROI_CFG; + } break; default: { } break; } diff --git a/mpp/mpi.cpp b/mpp/mpi.cpp index fe49d760..b6df5740 100644 --- a/mpp/mpi.cpp +++ b/mpp/mpi.cpp @@ -71,6 +71,9 @@ static MppCodingTypeInfo support_list[] = { #if HAVE_JPEGE { MPP_CTX_ENC, MPP_VIDEO_CodingMJPEG, "enc", "jpeg", }, #endif +#if HAVE_H265E + { MPP_CTX_ENC, MPP_VIDEO_CodingHEVC, "enc", "h265", }, +#endif }; #define check_mpp_ctx(ctx) _check_mpp_ctx(ctx, __FUNCTION__) diff --git a/test/mpi_enc_test.c b/test/mpi_enc_test.c index 47fee00d..bf38462f 100644 --- a/test/mpi_enc_test.c +++ b/test/mpi_enc_test.c @@ -296,8 +296,12 @@ MPP_RET test_mpp_setup(MpiEncTestData *p) codec_cfg->jpeg.change = MPP_ENC_JPEG_CFG_CHANGE_QP; codec_cfg->jpeg.quant = 10; } break; - case MPP_VIDEO_CodingVP8 : - case MPP_VIDEO_CodingHEVC : + case MPP_VIDEO_CodingVP8 : { + } break; + case MPP_VIDEO_CodingHEVC : { + codec_cfg->h265.change = MPP_ENC_H265_CFG_INTRA_QP_CHANGE; + codec_cfg->h265.intra_qp = 26; + } break; default : { mpp_err_f("support encoder coding type %d\n", codec_cfg->coding); } break;