[hal_h264e]: Add new h264 encoder hal module

New hal api will change interface to the following functions:

1. get_task - receive one task from encoder and process hw rate control.
2. gen_regs - generate register set according to different hardware.
3. start    - start the hardwara.
4. wait     - wait hardware process one task.
5. ret_task - return the processed task back to encoder.

NOTE: change some function to v2 to avoid linker conflict.
NOTE: vepu2_v2 status
1. Add svc and gop ref implement.
2. Without rc config. The QP is fixed.

Change-Id: I5fa890e8e23c0abbc5abb5ce44111c8a10ea1817
Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
This commit is contained in:
Herman Chen
2019-11-26 11:06:55 +08:00
parent a712acd78e
commit b514b956e3
8 changed files with 1783 additions and 9 deletions

View File

@@ -25,15 +25,6 @@ extern "C" {
extern const MppHalApi hal_api_h264e;
MPP_RET hal_h264e_init (void *hal, MppHalCfg *cfg);
MPP_RET hal_h264e_deinit (void *hal);
MPP_RET hal_h264e_gen_regs(void *hal, HalTaskInfo *task);
MPP_RET hal_h264e_start (void *hal, HalTaskInfo *task);
MPP_RET hal_h264e_wait (void *hal, HalTaskInfo *task);
MPP_RET hal_h264e_reset (void *hal);
MPP_RET hal_h264e_flush (void *hal);
MPP_RET hal_h264e_control (void *hal, MpiCmd cmd_type, void *param);
#ifdef __cplusplus
}
#endif

76
mpp/hal/inc/mpp_enc_hal.h Normal file
View File

@@ -0,0 +1,76 @@
/*
* 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 __MPP_ENC_HAL_H__
#define __MPP_ENC_HAL_H__
#include "mpp_hal.h"
typedef struct MppEncHalCfg_t {
// input for encoder
MppCodingType coding;
MppEncCfgSet *set;
MppEncCfgSet *cfg;
// output for enc_impl
HalWorkMode work_mode;
MppDeviceId device_id;
} MppEncHalCfg;
typedef struct MppEncHalApi_t {
char *name;
MppCodingType coding;
RK_U32 ctx_size;
RK_U32 flag;
MPP_RET (*init)(void *ctx, MppEncHalCfg *cfg);
MPP_RET (*deinit)(void *ctx);
// configure function
MPP_RET (*get_task)(void *ctx, HalEncTask *task);
MPP_RET (*gen_regs)(void *ctx, HalEncTask *task);
// hw operation function
MPP_RET (*start)(void *ctx, HalEncTask *task);
MPP_RET (*wait)(void *ctx, HalEncTask *task);
// return function
MPP_RET (*ret_task)(void *ctx, HalEncTask *task);
} MppEncHalApi;
typedef void* MppEncHal;
#ifdef __cplusplus
extern "C" {
#endif
MPP_RET mpp_enc_hal_init(MppEncHal *ctx, MppEncHalCfg *cfg);
MPP_RET mpp_enc_hal_deinit(MppEncHal ctx);
MPP_RET mpp_enc_hal_get_task(MppEncHal ctx, HalEncTask *task);
MPP_RET mpp_enc_hal_gen_regs(MppEncHal ctx, HalEncTask *task);
// start / wait hardware
MPP_RET mpp_enc_hal_start(MppEncHal ctx, HalEncTask *task);
MPP_RET mpp_enc_hal_wait(MppEncHal ctx, HalEncTask *task);
MPP_RET mpp_enc_hal_ret_task(MppEncHal ctx, HalEncTask *task);
#ifdef __cplusplus
}
#endif
#endif /*__MPP_ENC_HAL_H__*/

View File

@@ -1,6 +1,7 @@
# vim: syntax=cmake
include_directories(.)
include_directories(../../common/h264/)
include_directories(../../../codec/enc/h264/)
# hal h264 header
set(HAL_H264E_HDR
@@ -9,6 +10,8 @@ set(HAL_H264E_HDR
# hal h264 encoder sourse
set(HAL_H264E_SRC
hal_h264e_vepu2_v2.c
hal_h264e_vepu_v2.c
hal_h264e_vpu_tbl.c
hal_h264e_vepu2.c
hal_h264e_vepu1.c

View File

@@ -0,0 +1,806 @@
/*
* 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 "hal_h264e_vepu2_v2"
#include <string.h>
#include "mpp_env.h"
#include "mpp_mem.h"
#include "mpp_frame.h"
#include "mpp_common.h"
#include "mpp_device.h"
#include "mpp_rc.h"
#include "mpp_enc_hal.h"
#include "h264e_debug.h"
#include "h264e_syntax_new.h"
#include "h264e_slice.h"
#include "h264e_stream.h"
#include "hal_h264e_com.h"
#include "hal_h264e_vpu_tbl.h"
#include "hal_h264e_vepu_v2.h"
#include "hal_h264e_vepu2_reg_tbl.h"
typedef struct HalH264eVepu2Ctx_t {
MppEncCfgSet *cfg;
MppDevCtx dev_ctx;
RK_S32 frame_cnt;
/* buffers management */
HalH264eVepuBufs hw_bufs;
/* preprocess config */
HalH264eVepuPrep hw_prep;
/* input / recon / refer address config */
HalH264eVepuAddr hw_addr;
/* macroblock ratecontrol config */
HalH264eVepuMbRc hw_mbrc;
/* syntax for input from enc_impl */
RK_U32 updated;
SynH264eSps *sps;
SynH264ePps *pps;
H264eSlice *slice;
H264eFrmInfo *frms;
H264eReorderInfo *reorder;
H264eMarkingInfo *marking;
RcSyntax *rc_syn;
/* special TSVC stream header fixup */
size_t buf_size;
RK_U8 *src_buf;
RK_U8 *dst_buf;
/* syntax for output to enc_impl */
MppRcHalCfg hal_rc_cfg;
/* vepu2 macroblock ratecontrol context */
HalH264eVepuMbRcCtx rc_ctx;
H264eVpu2RegSet regs_set;
H264eVpu2RegSet regs_get;
} HalH264eVepu2Ctx;
static MPP_RET hal_h264e_vepu2_deinit_v2(void *hal)
{
HalH264eVepu2Ctx *p = (HalH264eVepu2Ctx *)hal;
hal_h264e_dbg_func("enter %p\n", p);
if (p->dev_ctx) {
mpp_device_deinit(p->dev_ctx);
p->dev_ctx = NULL;
}
h264e_vepu_buf_deinit(&p->hw_bufs);
if (p->rc_ctx) {
h264e_vepu_mbrc_deinit(p->rc_ctx);
p->rc_ctx = NULL;
}
MPP_FREE(p->src_buf);
MPP_FREE(p->dst_buf);
hal_h264e_dbg_func("leave %p\n", p);
return MPP_OK;
}
static MPP_RET hal_h264e_vepu2_init_v2(void *hal, MppEncHalCfg *cfg)
{
HalH264eVepu2Ctx *p = (HalH264eVepu2Ctx *)hal;
MPP_RET ret = MPP_OK;
MppDevCfg dev_cfg = {
.type = MPP_CTX_ENC, /* type */
.coding = MPP_VIDEO_CodingAVC, /* coding */
.platform = 0, /* platform */
.pp_enable = 0, /* pp_enable */
};
hal_h264e_dbg_func("enter %p\n", p);
p->cfg = cfg->cfg;
ret = mpp_device_init(&p->dev_ctx, &dev_cfg);
if (ret) {
mpp_err_f("mpp_device_init failed ret: %d\n", ret);
goto DONE;
}
ret = h264e_vepu_buf_init(&p->hw_bufs);
if (ret) {
mpp_err_f("init vepu buffer failed ret: %d\n", ret);
goto DONE;
}
ret = h264e_vepu_mbrc_init(&p->rc_ctx, &p->hw_mbrc);
if (ret) {
mpp_err_f("init mb rate control failed ret: %d\n", ret);
goto DONE;
}
/* create buffer to TSVC stream */
p->buf_size = SZ_128K;
p->src_buf = mpp_calloc(RK_U8, p->buf_size);
p->dst_buf = mpp_calloc(RK_U8, p->buf_size);
DONE:
if (ret)
hal_h264e_vepu2_deinit_v2(hal);
hal_h264e_dbg_func("leave %p\n", p);
return ret;
}
static RK_U32 update_vepu2_syntax(HalH264eVepu2Ctx *ctx, MppSyntax *syntax)
{
H264eSyntaxDesc *desc = syntax->data;
RK_S32 syn_num = syntax->number;
RK_U32 updated = 0;
RK_S32 i;
for (i = 0; i < syn_num; i++, desc++) {
switch (desc->type) {
case H264E_SYN_CFG : {
hal_h264e_dbg_detail("update cfg");
ctx->cfg = desc->p;
} break;
case H264E_SYN_SPS : {
hal_h264e_dbg_detail("update sps");
ctx->sps = desc->p;
} break;
case H264E_SYN_PPS : {
hal_h264e_dbg_detail("update pps");
ctx->pps = desc->p;
} break;
case H264E_SYN_SLICE : {
hal_h264e_dbg_detail("update slice");
ctx->slice = desc->p;
} break;
case H264E_SYN_FRAME : {
hal_h264e_dbg_detail("update frames");
ctx->frms = desc->p;
} break;
case H264E_SYN_RC : {
hal_h264e_dbg_detail("update rc");
ctx->rc_syn = desc->p;
} break;
case H264E_SYN_ROI :
case H264E_SYN_OSD :
default : {
mpp_log_f("invalid syntax type %d\n", desc->type);
} break;
}
updated |= SYN_TYPE_FLAG(desc->type);
}
return updated;
}
static MPP_RET hal_h264e_vepu2_get_task_v2(void *hal, HalEncTask *task)
{
HalH264eVepu2Ctx *ctx = (HalH264eVepu2Ctx *)hal;
RK_U32 updated = update_vepu2_syntax(ctx, &task->syntax);
MppEncPrepCfg *prep = &ctx->cfg->prep;
HalH264eVepuPrep *hw_prep = &ctx->hw_prep;
HalH264eVepuAddr *hw_addr = &ctx->hw_addr;
HalH264eVepuBufs *hw_bufs = &ctx->hw_bufs;
H264eFrmInfo *frms = ctx->frms;
hal_h264e_dbg_func("enter %p\n", hal);
if (updated & SYN_TYPE_FLAG(H264E_SYN_CFG)) {
h264e_vepu_buf_set_frame_size(hw_bufs, prep->width, prep->height);
/* preprocess setup */
h264e_vepu_prep_setup(hw_prep, prep);
h264e_vepu_mbrc_setup(ctx->rc_ctx, ctx->cfg);
}
if (updated & SYN_TYPE_FLAG(H264E_SYN_SLICE)) {
H264eSlice *slice = ctx->slice;
h264e_vepu_buf_set_cabac_idc(hw_bufs, slice->cabac_init_idc);
}
h264e_vepu_prep_get_addr(hw_prep, task->input, &hw_addr->orig);
MppBuffer recn = h264e_vepu_buf_get_frame_buffer(hw_bufs, frms->curr_idx);
MppBuffer refr = h264e_vepu_buf_get_frame_buffer(hw_bufs, frms->refr_idx);
EncFrmStatus info = frms->status;
size_t yuv_size = hw_bufs->yuv_size;
hw_addr->recn[0] = mpp_buffer_get_fd(recn);
hw_addr->refr[0] = mpp_buffer_get_fd(refr);
hw_addr->recn[1] = hw_addr->recn[0] + (yuv_size << 10);
hw_addr->refr[1] = hw_addr->refr[0] + (yuv_size << 10);
// update input rc cfg
ctx->hal_rc_cfg = frms->rc_cfg;
// prepare mb rc config
h264e_vepu_mbrc_prepare(ctx->rc_ctx, ctx->rc_syn, &info, &ctx->hw_mbrc);
hal_h264e_dbg_func("leave %p\n", hal);
return MPP_OK;
}
static MPP_RET hal_h264e_vepu2_gen_regs_v2(void *hal, HalEncTask *task)
{
//MPP_RET ret = MPP_OK;
HalH264eVepu2Ctx *ctx = (HalH264eVepu2Ctx *)hal;
HalH264eVepuBufs *hw_bufs = &ctx->hw_bufs;
HalH264eVepuPrep *hw_prep = &ctx->hw_prep;
HalH264eVepuAddr *hw_addr = &ctx->hw_addr;
HalH264eVepuMbRc *hw_mbrc = &ctx->hw_mbrc;
SynH264eSps *sps = ctx->sps;
SynH264ePps *pps = ctx->pps;
H264eSlice *slice = ctx->slice;
RK_U32 *reg = ctx->regs_set.val;
RK_U32 mb_w = ctx->sps->pic_width_in_mbs;
RK_U32 mb_h = ctx->sps->pic_height_in_mbs;
RK_U32 val = 0;
RK_S32 i = 0;
// TODO: Fix QP here for debug
hw_mbrc->qp_init = 26;
hw_mbrc->qp_max = 26;
hw_mbrc->qp_min = 26;
hal_h264e_dbg_func("enter %p\n", hal);
hal_h264e_dbg_detail("frame %d generate regs now", ctx->frms->seq_idx);
/* output buffer size is 64 bit address then 8 multiple size */
val = mpp_buffer_get_size(task->output);
val >>= 3;
val &= ~7;
H264E_HAL_SET_REG(reg, VEPU_REG_STR_BUF_LIMIT, val);
/*
* The hardware needs only the value for luma plane, because
* values of other planes are calculated internally based on
* format setting.
*/
val = VEPU_REG_INTRA_AREA_TOP(mb_h)
| VEPU_REG_INTRA_AREA_BOTTOM(mb_h)
| VEPU_REG_INTRA_AREA_LEFT(mb_w)
| VEPU_REG_INTRA_AREA_RIGHT(mb_w);
H264E_HAL_SET_REG(reg, VEPU_REG_INTRA_AREA_CTRL, val);
H264E_HAL_SET_REG(reg, VEPU_REG_STR_HDR_REM_MSB, 0);
H264E_HAL_SET_REG(reg, VEPU_REG_STR_HDR_REM_LSB, 0);
val = VEPU_REG_AXI_CTRL_READ_ID(0);
val |= VEPU_REG_AXI_CTRL_WRITE_ID(0);
val |= VEPU_REG_AXI_CTRL_BURST_LEN(16);
val |= VEPU_REG_AXI_CTRL_INCREMENT_MODE(0);
val |= VEPU_REG_AXI_CTRL_BIRST_DISCARD(0);
H264E_HAL_SET_REG(reg, VEPU_REG_AXI_CTRL, val);
H264E_HAL_SET_REG(reg, VEPU_QP_ADJUST_MAD_DELTA_ROI,
hw_mbrc->mad_qp_change);
val = 0;
if (mb_w * mb_h > 3600)
val = VEPU_REG_DISABLE_QUARTER_PIXEL_MV;
val |= VEPU_REG_CABAC_INIT_IDC(slice->cabac_init_idc);
if (pps->entropy_coding_mode)
val |= VEPU_REG_ENTROPY_CODING_MODE;
if (pps->transform_8x8_mode)
val |= VEPU_REG_H264_TRANS8X8_MODE;
if (sps->profile_idc > 31)
val |= VEPU_REG_H264_INTER4X4_MODE;
/*reg |= VEPU_REG_H264_STREAM_MODE;*/
val |= VEPU_REG_H264_SLICE_SIZE(hw_mbrc->slice_size_mb_rows);
H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL0, val);
RK_U32 scaler = MPP_MAX(1, 200 / (mb_w + mb_h));
RK_U32 skip_penalty = MPP_MIN(255, h264_skip_sad_penalty[hw_mbrc->qp_init] * scaler);
RK_U32 overfill_r = (hw_prep->src_w & 0x0f) ?
((16 - (hw_prep->src_w & 0x0f)) / 4) : 0;
RK_U32 overfill_b = (hw_prep->src_h & 0x0f) ?
(16 - (hw_prep->src_h & 0x0f)) : 0;
val = VEPU_REG_STREAM_START_OFFSET(0) | /* first_free_bit */
VEPU_REG_SKIP_MACROBLOCK_PENALTY(skip_penalty) |
VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(overfill_r) |
VEPU_REG_IN_IMG_CTRL_OVRFLB(overfill_b);
H264E_HAL_SET_REG(reg, VEPU_REG_ENC_OVER_FILL_STRM_OFFSET, val);
// When offset is zero row length should be total 16 aligned width
val = VEPU_REG_IN_IMG_CHROMA_OFFSET(0)
| VEPU_REG_IN_IMG_LUMA_OFFSET(0)
| VEPU_REG_IN_IMG_CTRL_ROW_LEN(mb_w * 16);
H264E_HAL_SET_REG(reg, VEPU_REG_INPUT_LUMA_INFO, val);
val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[0])
| VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[1]);
H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(0), val);
val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[2])
| VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[3]);
H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(1), val);
val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[4])
| VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[5]);
H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(2), val);
val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[6])
| VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[7]);
H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(3), val);
val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[8])
| VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[9]);
H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(4), val);
val = VEPU_REG_CHKPT_WORD_ERR_CHK1(hw_mbrc->cp_error[0])
| VEPU_REG_CHKPT_WORD_ERR_CHK0(hw_mbrc->cp_error[1]);
H264E_HAL_SET_REG(reg, VEPU_REG_CHKPT_WORD_ERR(0), val);
val = VEPU_REG_CHKPT_WORD_ERR_CHK1(hw_mbrc->cp_error[2])
| VEPU_REG_CHKPT_WORD_ERR_CHK0(hw_mbrc->cp_error[3]);
H264E_HAL_SET_REG(reg, VEPU_REG_CHKPT_WORD_ERR(1), val);
val = VEPU_REG_CHKPT_WORD_ERR_CHK1(hw_mbrc->cp_error[4])
| VEPU_REG_CHKPT_WORD_ERR_CHK0(hw_mbrc->cp_error[5]);
H264E_HAL_SET_REG(reg, VEPU_REG_CHKPT_WORD_ERR(2), val);
val = VEPU_REG_CHKPT_DELTA_QP_CHK6(hw_mbrc->cp_delta_qp[6])
| VEPU_REG_CHKPT_DELTA_QP_CHK5(hw_mbrc->cp_delta_qp[5])
| VEPU_REG_CHKPT_DELTA_QP_CHK4(hw_mbrc->cp_delta_qp[4])
| VEPU_REG_CHKPT_DELTA_QP_CHK3(hw_mbrc->cp_delta_qp[3])
| VEPU_REG_CHKPT_DELTA_QP_CHK2(hw_mbrc->cp_delta_qp[2])
| VEPU_REG_CHKPT_DELTA_QP_CHK1(hw_mbrc->cp_delta_qp[1])
| VEPU_REG_CHKPT_DELTA_QP_CHK0(hw_mbrc->cp_delta_qp[0]);
H264E_HAL_SET_REG(reg, VEPU_REG_CHKPT_DELTA_QP, val);
val = VEPU_REG_MAD_THRESHOLD(hw_mbrc->mad_threshold)
| VEPU_REG_IN_IMG_CTRL_FMT(hw_prep->src_fmt)
| VEPU_REG_IN_IMG_ROTATE_MODE(0)
| VEPU_REG_SIZE_TABLE_PRESENT; //FIXED
H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL1, val);
val = VEPU_REG_INTRA16X16_MODE(h264_intra16_favor[hw_mbrc->qp_init])
| VEPU_REG_INTER_MODE(h264_inter_favor[hw_mbrc->qp_init]);
H264E_HAL_SET_REG(reg, VEPU_REG_INTRA_INTER_MODE, val);
val = VEPU_REG_PPS_INIT_QP(pps->pic_init_qp)
| VEPU_REG_SLICE_FILTER_ALPHA(slice->slice_alpha_c0_offset_div2)
| VEPU_REG_SLICE_FILTER_BETA(slice->slice_beta_offset_div2)
| VEPU_REG_CHROMA_QP_OFFSET(pps->chroma_qp_index_offset)
| VEPU_REG_IDR_PIC_ID(slice->idr_pic_id);
if (slice->disable_deblocking_filter_idc)
val |= VEPU_REG_FILTER_DISABLE;
if (pps->constrained_intra_pred)
val |= VEPU_REG_CONSTRAINED_INTRA_PREDICTION;
H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL2, val);
H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_NEXT_PIC, 0);
H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_MV_OUT, 0);
MppBuffer cabac_table = hw_bufs->cabac_table;
RK_S32 cabac_table_fd = cabac_table ? mpp_buffer_get_fd(cabac_table) : 0;
H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_CABAC_TBL, cabac_table_fd);
val = VEPU_REG_ROI1_TOP_MB(mb_h)
| VEPU_REG_ROI1_BOTTOM_MB(mb_h)
| VEPU_REG_ROI1_LEFT_MB(mb_w)
| VEPU_REG_ROI1_RIGHT_MB(mb_w);
H264E_HAL_SET_REG(reg, VEPU_REG_ROI1, val);
val = VEPU_REG_ROI2_TOP_MB(mb_h)
| VEPU_REG_ROI2_BOTTOM_MB(mb_h)
| VEPU_REG_ROI2_LEFT_MB(mb_w)
| VEPU_REG_ROI2_RIGHT_MB(mb_w);
H264E_HAL_SET_REG(reg, VEPU_REG_ROI2, val);
H264E_HAL_SET_REG(reg, VEPU_REG_STABLILIZATION_OUTPUT, 0);
val = VEPU_REG_RGB2YUV_CONVERSION_COEFB(hw_prep->color_conversion_coeff_b)
| VEPU_REG_RGB2YUV_CONVERSION_COEFA(hw_prep->color_conversion_coeff_a);
H264E_HAL_SET_REG(reg, VEPU_REG_RGB2YUV_CONVERSION_COEF1, val);
val = VEPU_REG_RGB2YUV_CONVERSION_COEFE(hw_prep->color_conversion_coeff_e)
| VEPU_REG_RGB2YUV_CONVERSION_COEFC(hw_prep->color_conversion_coeff_c);
H264E_HAL_SET_REG(reg, VEPU_REG_RGB2YUV_CONVERSION_COEF2, val);
val = VEPU_REG_RGB2YUV_CONVERSION_COEFF(hw_prep->color_conversion_coeff_f);
H264E_HAL_SET_REG(reg, VEPU_REG_RGB2YUV_CONVERSION_COEF3, val);
val = VEPU_REG_RGB_MASK_B_MSB(hw_prep->b_mask_msb)
| VEPU_REG_RGB_MASK_G_MSB(hw_prep->g_mask_msb)
| VEPU_REG_RGB_MASK_R_MSB(hw_prep->r_mask_msb);
H264E_HAL_SET_REG(reg, VEPU_REG_RGB_MASK_MSB, val); //FIXED
{
RK_U32 diff_mv_penalty[3] = {0};
diff_mv_penalty[0] = h264_diff_mv_penalty4p[hw_mbrc->qp_init];
diff_mv_penalty[1] = h264_diff_mv_penalty[hw_mbrc->qp_init];
diff_mv_penalty[2] = h264_diff_mv_penalty[hw_mbrc->qp_init];
val = VEPU_REG_1MV_PENALTY(diff_mv_penalty[1])
| VEPU_REG_QMV_PENALTY(diff_mv_penalty[2])
| VEPU_REG_4MV_PENALTY(diff_mv_penalty[0]);
}
val |= VEPU_REG_SPLIT_MV_MODE_EN;
H264E_HAL_SET_REG(reg, VEPU_REG_MV_PENALTY, val);
val = VEPU_REG_H264_LUMA_INIT_QP(hw_mbrc->qp_init)
| VEPU_REG_H264_QP_MAX(hw_mbrc->qp_max)
| VEPU_REG_H264_QP_MIN(hw_mbrc->qp_min)
| VEPU_REG_H264_CHKPT_DISTANCE(hw_mbrc->cp_distance_mbs);
H264E_HAL_SET_REG(reg, VEPU_REG_QP_VAL, val);
val = VEPU_REG_ZERO_MV_FAVOR_D2(10);
H264E_HAL_SET_REG(reg, VEPU_REG_MVC_RELATE, val);
if (hw_prep->src_fmt < H264E_VPU_CSP_RGB565) {
val = VEPU_REG_OUTPUT_SWAP32
| VEPU_REG_OUTPUT_SWAP16
| VEPU_REG_OUTPUT_SWAP8
| VEPU_REG_INPUT_SWAP8
| VEPU_REG_INPUT_SWAP16
| VEPU_REG_INPUT_SWAP32;
} else if (hw_prep->src_fmt == H264E_VPU_CSP_ARGB8888) {
val = VEPU_REG_OUTPUT_SWAP32
| VEPU_REG_OUTPUT_SWAP16
| VEPU_REG_OUTPUT_SWAP8
| VEPU_REG_INPUT_SWAP32;
} else {
val = VEPU_REG_OUTPUT_SWAP32
| VEPU_REG_OUTPUT_SWAP16
| VEPU_REG_OUTPUT_SWAP8
| VEPU_REG_INPUT_SWAP16
| VEPU_REG_INPUT_SWAP32;
}
H264E_HAL_SET_REG(reg, VEPU_REG_DATA_ENDIAN, val);
val = VEPU_REG_PPS_ID(pps->pps_id)
| VEPU_REG_INTRA_PRED_MODE(h264_prev_mode_favor[hw_mbrc->qp_init])
| VEPU_REG_FRAME_NUM(slice->frame_num);
H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL3, val);
val = VEPU_REG_INTERRUPT_TIMEOUT_EN;
H264E_HAL_SET_REG(reg, VEPU_REG_INTERRUPT, val);
{
RK_U8 dmv_penalty[128] = {0};
RK_U8 dmv_qpel_penalty[128] = {0};
for (i = 0; i < 128; i++) {
dmv_penalty[i] = i;
dmv_qpel_penalty[i] = MPP_MIN(255, exp_golomb_signed(i));
}
for (i = 0; i < 128; i += 4) {
val = VEPU_REG_DMV_PENALTY_TABLE_BIT(dmv_penalty[i], 3);
val |= VEPU_REG_DMV_PENALTY_TABLE_BIT(dmv_penalty[i + 1], 2);
val |= VEPU_REG_DMV_PENALTY_TABLE_BIT(dmv_penalty[i + 2], 1);
val |= VEPU_REG_DMV_PENALTY_TABLE_BIT(dmv_penalty[i + 3], 0);
H264E_HAL_SET_REG(reg, VEPU_REG_DMV_PENALTY_TBL(i / 4), val);
val = VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT(
dmv_qpel_penalty[i], 3);
val |= VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT(
dmv_qpel_penalty[i + 1], 2);
val |= VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT(
dmv_qpel_penalty[i + 2], 1);
val |= VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT(
dmv_qpel_penalty[i + 3], 0);
H264E_HAL_SET_REG(reg, VEPU_REG_DMV_Q_PIXEL_PENALTY_TBL(i / 4), val);
}
}
/* set buffers addr */
H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_IN_LUMA, hw_addr->orig[0]);
H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_IN_CB, hw_addr->orig[1]);
H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_IN_CR, hw_addr->orig[2]);
H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_OUTPUT_STREAM,
mpp_buffer_get_fd(task->output));
MppBuffer nal_size_table = h264e_vepu_buf_get_nal_size_table(hw_bufs);
RK_S32 nal_size_table_fd = nal_size_table ? mpp_buffer_get_fd(nal_size_table) : 0;
H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_OUTPUT_CTRL, nal_size_table_fd);
H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_REC_LUMA, hw_addr->recn[0]);
H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_REC_CHROMA, hw_addr->recn[1]);
H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_REF_LUMA, hw_addr->refr[0]);
H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_REF_CHROMA, hw_addr->refr[1]);
/* set important encode mode info */
val = VEPU_REG_MB_HEIGHT(mb_h)
| VEPU_REG_MB_WIDTH(mb_w)
| VEPU_REG_PIC_TYPE(slice->idr_flag)
| VEPU_REG_ENCODE_FORMAT(3)
| VEPU_REG_ENCODE_ENABLE;
H264E_HAL_SET_REG(reg, VEPU_REG_ENCODE_START, val);
ctx->frame_cnt++;
hal_h264e_dbg_func("leave %p\n", hal);
return MPP_OK;
}
static MPP_RET hal_h264e_vepu2_start_v2(void *hal, HalEncTask *task)
{
MPP_RET ret = MPP_OK;
HalH264eVepu2Ctx *ctx = (HalH264eVepu2Ctx *)hal;
(void)task;
hal_h264e_dbg_func("enter %p\n", hal);
if (ctx->dev_ctx) {
RK_U32 *regs = ctx->regs_set.val;
hal_h264e_dbg_detail("vpu client is sending %d regs", VEPU2_H264E_NUM_REGS);
ret = mpp_device_send_reg(ctx->dev_ctx, regs, VEPU2_H264E_NUM_REGS);
if (ret)
mpp_err("mpp_device_send_reg failed ret %d", ret);
else
hal_h264e_dbg_detail("mpp_device_send_reg success!");
} else {
mpp_err("invalid device ctx: %p", ctx->dev_ctx);
ret = MPP_NOK;
}
hal_h264e_dbg_func("leave %p\n", hal);
return ret;
}
static void h264e_vepu2_get_mbrc(HalH264eVepuMbRc *mb_rc, H264eVpu2RegSet *reg)
{
RK_S32 i = 0;
RK_U32 cpt_prev = 0;
RK_U32 overflow = 0;
RK_U32 cpt_idx = VEPU_REG_CHECKPOINT(0) / 4;
RK_U32 *reg_val = reg->val;
mb_rc->hw_status = reg_val[VEPU_REG_INTERRUPT / 4];
mb_rc->out_strm_size = reg_val[VEPU_REG_STR_BUF_LIMIT / 4] / 8;
mb_rc->qp_sum = ((reg_val[VEPU_REG_QP_SUM_DIV2 / 4] >> 11) & 0x001fffff) * 2;
mb_rc->less_mad_count = (reg_val[VEPU_REG_MB_CTRL / 4] >> 16) & 0xffff;
mb_rc->rlc_count = reg_val[VEPU_REG_RLC_SUM / 4] & 0x3fffff;
for (i = 0; i < CHECK_POINTS_MAX; i++) {
RK_U32 cpt = VEPU_REG_CHECKPOINT_RESULT(reg_val[cpt_idx]);
if (cpt < cpt_prev)
overflow += (1 << 21);
cpt_prev = cpt;
mb_rc->cp_usage[i] = cpt + overflow;
cpt_idx += (i & 1);
}
}
static MPP_RET hal_h264e_vepu2_wait_v2(void *hal, HalEncTask *task)
{
HalH264eVepu2Ctx *ctx = (HalH264eVepu2Ctx *)hal;
HalH264eVepuMbRc *hw_mbrc = &ctx->hw_mbrc;
RK_U32 *regs_get = ctx->regs_get.val;
(void) task;
hal_h264e_dbg_func("enter %p\n", hal);
if (ctx->dev_ctx) {
RK_S32 hw_ret = mpp_device_wait_reg(ctx->dev_ctx, (RK_U32 *)regs_get,
VEPU2_H264E_NUM_REGS);
hal_h264e_dbg_detail("mpp_device_wait_reg: ret %d\n", hw_ret);
if (hw_ret != MPP_OK) {
mpp_err("hardware returns error:%d", hw_ret);
return MPP_ERR_VPUHW;
}
} else {
mpp_err("invalid device ctx: %p", ctx->dev_ctx);
return MPP_NOK;
}
h264e_vepu2_get_mbrc(hw_mbrc, &ctx->regs_get);
h264e_vepu_mbrc_update(ctx->rc_ctx, hw_mbrc);
/* On TSVC case modify AVC stream to TSVC stream */
MppEncCfgSet *cfg = ctx->cfg;
H264eSlice *slice = ctx->slice;
MppEncGopRef *ref = &cfg->gop_ref;
MppEncH264Cfg *h264 = &cfg->codec.h264;
if (h264->svc || ref->gop_cfg_enable) {
H264eSlice hw_slice;
MppBuffer buf = task->output;
RK_U8 *p = mpp_buffer_get_ptr(buf);
RK_U32 len = hw_mbrc->out_strm_size;
RK_S32 size = mpp_buffer_get_size(buf);
RK_S32 hw_len_bit = 0;
RK_S32 sw_len_bit = 0;
RK_S32 hw_len_byte = 0;
RK_S32 sw_len_byte = 0;
RK_S32 diff_size = 0;
RK_S32 tail_0bit = 0;
RK_U8 tail_byte = 0;
RK_U8 tail_tmp = 0;
RK_U8 *dst_buf = NULL;
RK_S32 buf_size;
RK_S32 prefix_bit = 0;
RK_S32 prefix_byte = 0;
RK_S32 more_buf = 0;
while (len > ctx->buf_size - 16) {
ctx->buf_size *= 2;
more_buf = 1;
}
if (more_buf) {
MPP_FREE(ctx->src_buf);
MPP_FREE(ctx->dst_buf);
ctx->src_buf = mpp_malloc(RK_U8, ctx->buf_size);
ctx->dst_buf = mpp_malloc(RK_U8, ctx->buf_size);
}
memset(ctx->dst_buf, 0, ctx->buf_size);
dst_buf = ctx->dst_buf;
buf_size = ctx->buf_size;
// copy hw stream to stream buffer first
memcpy(ctx->src_buf, p, len);
// prepare hw_slice with some current setup
memcpy(&hw_slice, slice, sizeof(hw_slice));
// set hw_slice to vepu2 default hardware config
hw_slice.max_num_ref_frames = 1;
hw_slice.pic_order_cnt_type = 2;
hw_slice.log2_max_frame_num = 16;
hw_slice.log2_max_poc_lsb = 16;
hw_len_bit = h264e_slice_read(&hw_slice, ctx->src_buf, size);
if (h264->svc) {
H264ePrefixNal prefix;
prefix.idr_flag = slice->idr_flag;
prefix.nal_ref_idc = slice->nal_reference_idc;
prefix.priority_id = 0;
prefix.no_inter_layer_pred_flag = 1;
prefix.dependency_id = 0;
prefix.quality_id = 0;
prefix.temporal_id = task->temporal_id;
prefix.use_ref_base_pic_flag = 0;
prefix.discardable_flag = 0;
prefix.output_flag = 1;
prefix_bit = h264e_slice_write_prefix_nal_unit_svc(&prefix, dst_buf, buf_size);
prefix_byte = prefix_bit /= 8;
h264e_dbg_slice("prefix_len %d\n", prefix_byte);
dst_buf += prefix_byte;
buf_size -= prefix_byte;
}
// write new header to header buffer
sw_len_bit = h264e_slice_write(slice, dst_buf, buf_size);
h264e_slice_read(slice, dst_buf, size);
hw_len_byte = (hw_len_bit + 7) / 8;
sw_len_byte = (sw_len_bit + 7) / 8;
tail_byte = ctx->src_buf[len - 1];
tail_tmp = tail_byte;
while (!(tail_tmp & 1) && tail_0bit < 8) {
tail_tmp >>= 1;
tail_0bit++;
}
h264e_dbg_slice("tail_byte %02x bit %d\n", tail_byte, tail_0bit);
mpp_assert(tail_0bit < 8);
// move the reset slice data from src buffer to dst buffer
diff_size = h264e_slice_move(dst_buf, ctx->src_buf,
sw_len_bit, hw_len_bit, len);
h264e_dbg_slice("tail 0x%02x %d hw_len_bit %d sw_len_bit %d len %d hw_len_byte %d sw_len_byte %d diff %d\n",
tail_byte, tail_0bit, hw_len_bit, sw_len_bit, len, hw_len_byte, sw_len_byte, diff_size);
if (slice->entropy_coding_mode) {
memcpy(dst_buf + sw_len_byte, ctx->src_buf + hw_len_byte,
len - hw_len_byte);
len += prefix_byte;
memcpy(p, ctx->dst_buf, len - hw_len_byte + sw_len_byte);
// clear the tail data
if (sw_len_byte < hw_len_byte)
memset(p + len - hw_len_byte + sw_len_byte, 0, hw_len_byte - sw_len_byte);
len = len - hw_len_byte + sw_len_byte;
} else {
RK_S32 hdr_diff_bit = sw_len_bit - hw_len_bit;
RK_S32 bit_len = len * 8 - tail_0bit + hdr_diff_bit;
RK_S32 new_len = (bit_len + diff_size * 8 + 7) / 8;
dst_buf[new_len] = 0;
h264e_dbg_slice("frm %d len %d bit hw %d sw %d byte hw %d sw %d diff %d -> %d\n",
ctx->frms->seq_idx, len, hw_len_bit, sw_len_bit,
hw_len_byte, sw_len_byte, diff_size, new_len);
new_len += prefix_byte;
memcpy(p, ctx->dst_buf, new_len);
p[new_len] = 0;
len = new_len;
}
hw_mbrc->out_strm_size = len;
}
hal_h264e_dbg_func("leave %p\n", hal);
return MPP_OK;
}
static MPP_RET hal_h264e_vepu2_ret_task_v2(void *hal, HalEncTask *task)
{
HalH264eVepu2Ctx *ctx = (HalH264eVepu2Ctx *)hal;
RK_U32 mb_w = ctx->sps->pic_width_in_mbs;
RK_U32 mb_h = ctx->sps->pic_height_in_mbs;
RK_U32 mbs = mb_w * mb_h;
hal_h264e_dbg_func("enter %p\n", hal);
task->length = ctx->hw_mbrc.out_strm_size;
ctx->hal_rc_cfg.bit_real = task->length;
ctx->hal_rc_cfg.quality_real = ctx->hw_mbrc.qp_sum / mbs;
task->hal_ret.data = &ctx->hal_rc_cfg;
task->hal_ret.number = 1;
hal_h264e_dbg_func("leave %p\n", hal);
return MPP_OK;
}
const MppEncHalApi hal_h264e_vepu2 = {
.name = "hal_h264e_vepu2",
.coding = MPP_VIDEO_CodingAVC,
.ctx_size = sizeof(HalH264eVepu2Ctx),
.flag = 0,
.init = hal_h264e_vepu2_init_v2,
.deinit = hal_h264e_vepu2_deinit_v2,
.get_task = hal_h264e_vepu2_get_task_v2,
.gen_regs = hal_h264e_vepu2_gen_regs_v2,
.start = hal_h264e_vepu2_start_v2,
.wait = hal_h264e_vepu2_wait_v2,
.ret_task = hal_h264e_vepu2_ret_task_v2,
};

View File

@@ -0,0 +1,24 @@
/*
* 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_H264E_VEPU2_H__
#define __HAL_H264E_VEPU2_H__
#include "mpp_enc_hal.h"
extern const MppEncHalApi hal_h264e_vepu2;
#endif

View File

@@ -0,0 +1,643 @@
/*
* Copyright 2015 - 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_h264e_vepu_v2"
#include <string.h>
#include "mpp_mem.h"
#include "mpp_common.h"
#include "mpp_buffer.h"
#include "hal_h264e_debug.h"
#include "hal_h264e_com.h"
#include "hal_h264e_vepu_v2.h"
#include "hal_h264e_vpu_tbl_v2.h"
typedef struct HalH264eVepuMbRcImpl_t {
RK_S32 width;
RK_S32 height;
RK_S32 mb_w;
RK_S32 mb_h;
RK_S32 pels;
RK_S32 mbs;
RK_S32 bits_per_pic;
RK_S32 mb_bit_rc_enable;
/* frame rate control */
RK_S32 fps_in_num;
RK_S32 fps_in_denorm;
RK_S32 fps_out_num;
RK_S32 fps_out_denorm;
RK_S32 fps_count;
RK_S32 fps_step;
RK_S32 fps_threshold;
/*
* MAD based QP adjustment
* mad_qp_change [-8..7]
* mad_threshold MAD threshold div256
*/
RK_S32 mad_qp_change;
RK_S32 mad_threshold;
/*
* check point parameter
*/
RK_S32 check_point_count;
RK_S32 check_point_distance;
/* estimated first I frame qp */
RK_S32 qp_init_est;
} HalH264eVepuMbRcImpl;
static void vepu_swap_endian(RK_U32 *buf, RK_S32 size_bytes)
{
RK_U32 i = 0;
RK_S32 words = size_bytes / 4;
RK_U32 val, val2, tmp, tmp2;
mpp_assert((size_bytes % 8) == 0);
while (words > 0) {
val = buf[i];
tmp = 0;
tmp |= (val & 0xFF) << 24;
tmp |= (val & 0xFF00) << 8;
tmp |= (val & 0xFF0000) >> 8;
tmp |= (val & 0xFF000000) >> 24;
{
val2 = buf[i + 1];
tmp2 = 0;
tmp2 |= (val2 & 0xFF) << 24;
tmp2 |= (val2 & 0xFF00) << 8;
tmp2 |= (val2 & 0xFF0000) >> 8;
tmp2 |= (val2 & 0xFF000000) >> 24;
buf[i] = tmp2;
words--;
i++;
}
buf[i] = tmp;
words--;
i++;
}
}
static void vepu_write_cabac_table(MppBuffer buf, RK_S32 cabac_init_idc)
{
const RK_S32(*context)[460][2];
RK_S32 i, j, qp;
RK_U8 table[H264E_CABAC_TABLE_BUF_SIZE] = {0};
for (qp = 0; qp < 52; qp++) { /* All QP values */
for (j = 0; j < 2; j++) { /* Intra/Inter */
if (j == 0)
/*lint -e(545) */
context = &h264_context_init_intra;
else
/*lint -e(545) */
context = &h264_context_init[cabac_init_idc];
for (i = 0; i < 460; i++) {
RK_S32 m = (RK_S32)(*context)[i][0];
RK_S32 n = (RK_S32)(*context)[i][1];
RK_S32 pre_ctx_state = H264E_HAL_CLIP3(((m * (RK_S32)qp) >> 4)
+ n, 1, 126);
if (pre_ctx_state <= 63)
table[qp * 464 * 2 + j * 464 + i] =
(RK_U8)((63 - pre_ctx_state) << 1);
else
table[qp * 464 * 2 + j * 464 + i] =
(RK_U8)(((pre_ctx_state - 64) << 1) | 1);
}
}
}
vepu_swap_endian((RK_U32 *)table, H264E_CABAC_TABLE_BUF_SIZE);
mpp_buffer_write(buf, 0, table, H264E_CABAC_TABLE_BUF_SIZE);
}
MPP_RET h264e_vepu_buf_init(HalH264eVepuBufs *bufs)
{
MPP_RET ret = MPP_OK;
hal_h264e_dbg_buffer("enter %p\n", bufs);
memset(bufs, 0, sizeof(*bufs));
// do not create buffer on cavlc case
bufs->cabac_init_idc = -1;
ret = mpp_buffer_group_get_internal(&bufs->group, MPP_BUFFER_TYPE_ION);
if (ret)
mpp_err_f("get buffer group failed ret %d\n", ret);
hal_h264e_dbg_buffer("leave %p\n", bufs);
return ret;
}
MPP_RET h264e_vepu_buf_deinit(HalH264eVepuBufs *bufs)
{
RK_S32 i;
hal_h264e_dbg_buffer("enter %p\n", bufs);
if (bufs->cabac_table)
mpp_buffer_put(bufs->cabac_table);
if (bufs->nal_size_table)
mpp_buffer_put(bufs->nal_size_table);
for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(bufs->frm_buf); i++) {
if (bufs->frm_buf[i])
mpp_buffer_put(bufs->frm_buf[i]);
}
if (bufs->group)
mpp_buffer_group_put(bufs->group);
memset(bufs, 0, sizeof(*bufs));
bufs->cabac_init_idc = -1;
hal_h264e_dbg_buffer("leave %p\n", bufs);
return MPP_OK;
}
MPP_RET h264e_vepu_buf_set_cabac_idc(HalH264eVepuBufs *bufs, RK_S32 idc)
{
hal_h264e_dbg_buffer("enter %p\n", bufs);
if (idc >= 0 && !bufs->cabac_table)
mpp_buffer_get(bufs->group, &bufs->cabac_table, H264E_CABAC_TABLE_BUF_SIZE);
if (bufs->cabac_table && idc != bufs->cabac_init_idc && idc >= 0)
vepu_write_cabac_table(bufs->cabac_table, idc);
bufs->cabac_init_idc = idc;
hal_h264e_dbg_buffer("leave %p\n", bufs);
return MPP_OK;
}
MPP_RET h264e_vepu_buf_set_frame_size(HalH264eVepuBufs *bufs, RK_S32 w, RK_S32 h)
{
RK_S32 aligned_w = MPP_ALIGN(w, 16);
RK_S32 aligned_h = MPP_ALIGN(h, 16);
size_t yuv_size = aligned_w * aligned_h;
size_t frm_size = yuv_size * 3 / 2;
RK_S32 i;
RK_S32 cnt = (RK_S32)MPP_ARRAY_ELEMS(bufs->frm_buf);
hal_h264e_dbg_buffer("enter %p\n", bufs);
mpp_assert(frm_size);
if (frm_size != bufs->frm_size) {
if (bufs->frm_size) {
/* reallocate only on larger frame size to save time */
mpp_log("new frame size [%d:%d] require buffer %d not equal to %d\n",
w, h, frm_size, bufs->frm_size);
}
for (i = 0; i < cnt; i++) {
if (bufs->frm_buf[i]) {
mpp_buffer_put(bufs->frm_buf[i]);
bufs->frm_buf[i] = NULL;
bufs->frm_cnt--;
}
}
}
bufs->mb_h = aligned_h >> 4;
if (bufs->mb_h)
bufs->nal_tab_size = MPP_ALIGN((bufs->mb_h + 1) * sizeof(RK_U32), 8);
else
bufs->nal_tab_size = 0;
bufs->yuv_size = yuv_size;
bufs->frm_size = frm_size;
hal_h264e_dbg_buffer("leave %p\n", bufs);
return MPP_OK;
}
MppBuffer h264e_vepu_buf_get_nal_size_table(HalH264eVepuBufs *bufs)
{
MppBuffer buf = bufs->nal_size_table;
hal_h264e_dbg_buffer("enter %p\n", bufs);
if (NULL == buf) {
mpp_buffer_get(bufs->group, &buf, bufs->nal_tab_size);
mpp_assert(buf);
bufs->nal_size_table = buf;
}
hal_h264e_dbg_buffer("leave %p\n", bufs);
return buf;
}
MppBuffer h264e_vepu_buf_get_frame_buffer(HalH264eVepuBufs *bufs, RK_S32 index)
{
MppBuffer buf = bufs->frm_buf[index];
hal_h264e_dbg_buffer("enter\n", bufs);
if (NULL == buf) {
mpp_buffer_get(bufs->group, &buf, bufs->frm_size);
mpp_assert(buf);
bufs->frm_buf[index] = buf;
bufs->frm_cnt++;
}
hal_h264e_dbg_buffer("leave %p\n", bufs);
return buf;
}
static H264eVpuCsp fmt_to_vepu_csp_yuv[MPP_FMT_YUV_BUTT] = {
H264E_VPU_CSP_YUV420SP, // MPP_FMT_YUV420SP /* YYYY... UV... (NV12) */
H264E_VPU_CSP_NONE, // MPP_FMT_YUV420SP_10BIT ///< Not part of ABI
H264E_VPU_CSP_NONE, // MPP_FMT_YUV422SP /* YYYY... UVUV... (NV16) */
H264E_VPU_CSP_NONE, // MPP_FMT_YUV422SP_10BIT ///< Not part of ABI
H264E_VPU_CSP_YUV420P, // MPP_FMT_YUV420P /* YYYY... U...V... (I420) */
H264E_VPU_CSP_NONE, // MPP_FMT_YUV420SP_VU /* YYYY... VUVUVU... (NV21) */
H264E_VPU_CSP_NONE, // MPP_FMT_YUV422P /* YYYY... UU...VV...(422P) */
H264E_VPU_CSP_NONE, // MPP_FMT_YUV422SP_VU /* YYYY... VUVUVU... (NV61) */
H264E_VPU_CSP_YUYV422, // MPP_FMT_YUV422_YUYV /* YUYVYUYV... (YUY2) */
H264E_VPU_CSP_UYVY422, // MPP_FMT_YUV422_UYVY /* UYVYUYVY... (UYVY) */
H264E_VPU_CSP_NONE, // MPP_FMT_YUV400 /* YYYY... */
H264E_VPU_CSP_NONE, // MPP_FMT_YUV440SP /* YYYY... UVUV... */
H264E_VPU_CSP_NONE, // MPP_FMT_YUV411SP /* YYYY... UV... */
H264E_VPU_CSP_NONE, // MPP_FMT_YUV444SP /* YYYY... UVUVUVUV... */
};
static H264eVpuCsp fmt_to_vepu_csp_rgb[MPP_FMT_RGB_BUTT - MPP_FRAME_FMT_RGB] = {
H264E_VPU_CSP_RGB565, // MPP_FMT_RGB565 /* 16-bit RGB */
H264E_VPU_CSP_RGB565, // MPP_FMT_BGR565 /* 16-bit RGB */
H264E_VPU_CSP_RGB555, // MPP_FMT_RGB555 /* 15-bit RGB */
H264E_VPU_CSP_RGB555, // MPP_FMT_BGR555 /* 15-bit RGB */
H264E_VPU_CSP_RGB444, // MPP_FMT_RGB444 /* 12-bit RGB */
H264E_VPU_CSP_RGB444, // MPP_FMT_BGR444 /* 12-bit RGB */
H264E_VPU_CSP_RGB888, // MPP_FMT_RGB888 /* 24-bit RGB */
H264E_VPU_CSP_RGB888, // MPP_FMT_BGR888 /* 24-bit RGB */
H264E_VPU_CSP_RGB101010, // MPP_FMT_RGB101010 /* 30-bit RGB */
H264E_VPU_CSP_RGB101010, // MPP_FMT_BGR101010 /* 30-bit RGB */
H264E_VPU_CSP_ARGB8888, // MPP_FMT_ARGB8888 /* 32-bit RGB */
H264E_VPU_CSP_ARGB8888, // MPP_FMT_ABGR8888 /* 32-bit RGB */
};
static RK_S32 fmt_to_vepu_mask_msb[MPP_FMT_RGB_BUTT - MPP_FRAME_FMT_RGB][3] = {
// R G B // mask msb position
{ 15, 10, 4, }, // MPP_FMT_RGB565 /* 16-bit RGB */
{ 4, 10, 15, }, // MPP_FMT_BGR565 /* 16-bit RGB */
{ 14, 9, 4, }, // MPP_FMT_RGB555 /* 15-bit RGB */
{ 4, 9, 14, }, // MPP_FMT_BGR555 /* 15-bit RGB */
{ 11, 7, 3, }, // MPP_FMT_RGB444 /* 12-bit RGB */
{ 3, 7, 11, }, // MPP_FMT_BGR444 /* 12-bit RGB */
{ 23, 15, 7, }, // MPP_FMT_RGB888 /* 24-bit RGB */
{ 7, 15, 23, }, // MPP_FMT_BGR888 /* 24-bit RGB */
{ 29, 19, 9, }, // MPP_FMT_RGB101010 /* 30-bit RGB */
{ 9, 19, 29, }, // MPP_FMT_BGR101010 /* 30-bit RGB */
{ 23, 15, 7, }, // MPP_FMT_ARGB8888 /* 32-bit RGB */
{ 7, 15, 23, }, // MPP_FMT_ABGR8888 /* 32-bit RGB */
};
MPP_RET h264e_vepu_prep_setup(HalH264eVepuPrep *prep, MppEncPrepCfg *cfg)
{
MPP_RET ret = MPP_OK;
MppFrameFormat format = cfg->format;
hal_h264e_dbg_buffer("enter\n");
prep->src_fmt = format;
prep->src_w = cfg->width;
prep->src_h = cfg->height;
if (format < MPP_FRAME_FMT_RGB) {
// YUV case
prep->src_fmt = fmt_to_vepu_csp_yuv[format];
if (prep->src_fmt == H264E_VPU_CSP_NONE) {
mpp_err("vepu do not support input frame format %d\n", format);
ret = MPP_NOK;
}
prep->r_mask_msb = 0;
prep->g_mask_msb = 0;
prep->b_mask_msb = 0;
prep->color_conversion_coeff_a = 0;
prep->color_conversion_coeff_b = 0;
prep->color_conversion_coeff_c = 0;
prep->color_conversion_coeff_e = 0;
prep->color_conversion_coeff_f = 0;
} else {
// RGB case
RK_S32 rgb_idx = format - MPP_FRAME_FMT_RGB;
mpp_assert(rgb_idx < MPP_FMT_RGB_BUTT - MPP_FRAME_FMT_RGB);
prep->src_fmt = fmt_to_vepu_csp_rgb[rgb_idx];
if (prep->src_fmt == H264E_VPU_CSP_NONE) {
mpp_err("vepu do not support input frame format %d\n", format);
ret = MPP_NOK;
}
prep->r_mask_msb = fmt_to_vepu_mask_msb[rgb_idx][0];
prep->g_mask_msb = fmt_to_vepu_mask_msb[rgb_idx][1];
prep->b_mask_msb = fmt_to_vepu_mask_msb[rgb_idx][2];
switch (cfg->color) {
case MPP_FRAME_SPC_RGB : {
/* BT.601 */
/* Y = 0.2989 R + 0.5866 G + 0.1145 B
* Cb = 0.5647 (B - Y) + 128
* Cr = 0.7132 (R - Y) + 128
*/
prep->color_conversion_coeff_a = 19589;
prep->color_conversion_coeff_b = 38443;
prep->color_conversion_coeff_c = 7504;
prep->color_conversion_coeff_e = 37008;
prep->color_conversion_coeff_f = 46740;
} break;
case MPP_FRAME_SPC_BT709 : {
/* BT.709 */
/* Y = 0.2126 R + 0.7152 G + 0.0722 B
* Cb = 0.5389 (B - Y) + 128
* Cr = 0.6350 (R - Y) + 128
*/
prep->color_conversion_coeff_a = 13933;
prep->color_conversion_coeff_b = 46871;
prep->color_conversion_coeff_c = 4732;
prep->color_conversion_coeff_e = 35317;
prep->color_conversion_coeff_f = 41615;
} break;
default : {
prep->color_conversion_coeff_a = 19589;
prep->color_conversion_coeff_b = 38443;
prep->color_conversion_coeff_c = 7504;
prep->color_conversion_coeff_e = 37008;
prep->color_conversion_coeff_f = 46740;
} break;
}
}
RK_S32 hor_stride = cfg->hor_stride;
RK_S32 ver_stride = cfg->ver_stride;
prep->offset_cb = 0;
prep->offset_cr = 0;
switch (format) {
case MPP_FMT_YUV420SP : {
prep->offset_cb = hor_stride * ver_stride;
prep->size_y = hor_stride * MPP_ALIGN(prep->src_h, 16);
prep->size_c = hor_stride / 2 * MPP_ALIGN(prep->src_h / 2, 8);
} break;
case MPP_FMT_YUV420P : {
prep->offset_cb = hor_stride * ver_stride;
prep->offset_cr = prep->offset_cb + ((hor_stride * ver_stride) / 4);
prep->size_y = hor_stride * MPP_ALIGN(prep->src_h, 16);
prep->size_c = hor_stride / 2 * MPP_ALIGN(prep->src_h / 2, 8);
} break;
case MPP_FMT_YUV422_YUYV :
case MPP_FMT_YUV422_UYVY : {
prep->size_y = hor_stride * 2 * MPP_ALIGN(prep->src_h, 16);
prep->size_c = 0;
} break;
case MPP_FMT_RGB565 :
case MPP_FMT_BGR444 : {
prep->size_y = hor_stride * 2 * MPP_ALIGN(prep->src_h, 16);
prep->size_c = 0;
} break;
case MPP_FMT_BGR888 :
case MPP_FMT_RGB888 :
case MPP_FMT_ARGB8888 :
case MPP_FMT_ABGR8888 :
case MPP_FMT_BGR101010 : {
prep->size_y = hor_stride * 4 * MPP_ALIGN(prep->src_h, 16);
prep->size_c = 0;
} break;
default: {
mpp_err_f("invalid format %d", format);
ret = MPP_NOK;
}
}
hal_h264e_dbg_buffer("leave\n");
return ret;
}
MPP_RET h264e_vepu_prep_get_addr(HalH264eVepuPrep *prep, MppBuffer buffer,
RK_U32 (*addr)[3])
{
RK_U32 fd = (RK_U32)mpp_buffer_get_fd(buffer);
size_t size = mpp_buffer_get_size(buffer);
hal_h264e_dbg_buffer("enter\n");
(*addr)[0] = fd;
(*addr)[1] = fd + (prep->offset_cb << 10);
(*addr)[2] = fd + (prep->offset_cr << 10);
if (size < prep->size_y)
mpp_err("warnning: input buffer size 0x%x is smaller then required size 0x%x",
size, prep->size_y);
if (prep->size_c && (prep->offset_cb || prep->offset_cr)) {
if (prep->offset_cb && (size < prep->offset_cb + prep->size_c))
mpp_err("warnning: input buffer size 0x%x is smaller then cb requirement 0x%x + 0x%x",
size, prep->offset_cb, prep->size_c);
if (prep->offset_cr && (size < prep->offset_cr + prep->size_c))
mpp_err("warnning: input buffer size 0x%x is smaller then cb requirement 0x%x + 0x%x",
size, prep->offset_cr, prep->size_c);
}
hal_h264e_dbg_buffer("leave\n");
return MPP_OK;
}
MPP_RET h264e_vepu_mbrc_init(HalH264eVepuMbRcCtx *ctx, HalH264eVepuMbRc *mbrc)
{
MPP_RET ret = MPP_OK;
HalH264eVepuMbRcImpl *p = mpp_calloc(HalH264eVepuMbRcImpl, 1);
if (!p) {
mpp_err_f("failed to alloc rate control context\n");
ret = MPP_ERR_NOMEM;
}
memset(mbrc, 0, sizeof(*mbrc));
mbrc->qp_init = -1;
mbrc->qp_max = 48;
mbrc->qp_min = 16;
*ctx = p;
return ret;
}
MPP_RET h264e_vepu_mbrc_deinit(HalH264eVepuMbRcCtx ctx)
{
MPP_FREE(ctx);
return MPP_OK;
}
static RK_S32 qp_tbl[2][13] = {
{
26, 36, 48, 63, 85, 110, 152, 208, 313, 427, 936,
1472, 0x7fffffff
},
{42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6}
};
MPP_RET h264e_vepu_mbrc_setup(HalH264eVepuMbRcCtx ctx, MppEncCfgSet*cfg)
{
HalH264eVepuMbRcImpl *p = (HalH264eVepuMbRcImpl *)ctx;
MppEncH264Cfg *codec = &cfg->codec.h264;
MppEncPrepCfg *prep = &cfg->prep;
MppEncRcCfg *rc = &cfg->rc;
hal_h264e_dbg_rc("enter\n");
// get necessary parameter from config
p->width = prep->width;
p->height = prep->height;
p->mb_w = MPP_ALIGN(prep->width, 16) / 16;
p->mb_h = MPP_ALIGN(prep->height, 16) / 16;
p->pels = p->width * p->height;
p->mbs = p->mb_w * p->mb_h;
p->bits_per_pic = axb_div_c(rc->bps_target, rc->fps_out_denorm,
rc->fps_out_num);
mpp_assert(p->pels);
// frame rate control
mpp_assert(rc->fps_out_num / rc->fps_out_denorm <= rc->fps_in_num / rc->fps_in_denorm);
p->fps_in_num = rc->fps_in_num;
p->fps_in_denorm = rc->fps_in_denorm;
p->fps_out_num = rc->fps_out_num;
p->fps_out_denorm = rc->fps_out_denorm;
p->fps_step = rc->fps_in_denorm * rc->fps_out_num;
p->fps_threshold = rc->fps_in_num * rc->fps_out_denorm;
p->fps_count = p->fps_threshold;
// if not constant
p->mb_bit_rc_enable = !(rc->rc_mode == MPP_ENC_RC_MODE_VBR &&
rc->quality == MPP_ENC_RC_QUALITY_CQP);
// init first frame QP
if (p->bits_per_pic > 1000000)
p->qp_init_est = codec->qp_min;
else {
RK_S32 upscale = 8000;
RK_S32 i = -1;
RK_S32 bits_per_pic = p->bits_per_pic;
RK_S32 mbs = p->mbs;
bits_per_pic >>= 5;
bits_per_pic *= mbs + 250;
bits_per_pic /= 350 + (3 * mbs) / 4;
bits_per_pic = axb_div_c(bits_per_pic, upscale, mbs << 6);
while (qp_tbl[0][++i] < bits_per_pic);
p->qp_init_est = qp_tbl[1][i];
}
hal_h264e_dbg_rc("estimated init qp %d\n", p->qp_init_est);
// init first frame mad parameter
p->mad_qp_change = 2;
p->mad_threshold = 256 * 6;
// init check point position
if (p->mb_bit_rc_enable) {
p->check_point_count = MPP_MIN(p->mb_h - 1, CHECK_POINTS_MAX);
p->check_point_distance = p->mbs / (p->check_point_count + 1);
} else {
p->check_point_count = 0;
p->check_point_distance = 0;
}
hal_h264e_dbg_rc("leave\n");
return MPP_OK;
}
MPP_RET h264e_vepu_mbrc_prepare(HalH264eVepuMbRcCtx ctx, RcSyntax *rc,
EncFrmStatus *info, HalH264eVepuMbRc *mbrc)
{
HalH264eVepuMbRcImpl *p = (HalH264eVepuMbRcImpl *)ctx;
RK_S32 target_bits = rc->bit_target;
RK_S32 target_step = target_bits / (p->check_point_count + 1);
RK_S32 target_sum = 0;
RK_S32 tmp;
RK_S32 i;
mpp_assert(target_step >= 0);
(void) info;
for (i = 0; i < VEPU_CHECK_POINTS_MAX; i++) {
target_sum += target_step;
mbrc->cp_target[i] = mpp_clip(target_sum / 32, -32768, 32767);
}
tmp = target_step / 8;
mbrc->cp_error[0] = -tmp * 3;
mbrc->cp_delta_qp[0] = -3;
mbrc->cp_error[1] = -tmp * 2;
mbrc->cp_delta_qp[1] = -2;
mbrc->cp_error[2] = -tmp * 1;
mbrc->cp_delta_qp[2] = -1;
mbrc->cp_error[3] = tmp * 1;
mbrc->cp_delta_qp[3] = 0;
mbrc->cp_error[4] = tmp * 2;
mbrc->cp_delta_qp[4] = 1;
mbrc->cp_error[5] = tmp * 3;
mbrc->cp_delta_qp[5] = 2;
mbrc->cp_error[6] = tmp * 4;
mbrc->cp_delta_qp[6] = 3;
mbrc->mad_qp_change = 2;
mbrc->mad_threshold = 2;
mbrc->cp_distance_mbs = p->check_point_distance;
return MPP_OK;
}
MPP_RET h264e_vepu_mbrc_update(HalH264eVepuMbRcCtx ctx, HalH264eVepuMbRc *mbrc)
{
HalH264eVepuMbRcImpl *p = (HalH264eVepuMbRcImpl *)ctx;
(void) p;
(void) mbrc;
hal_h264e_dbg_rc("enter\n");
hal_h264e_dbg_rc("leave\n");
return MPP_OK;
}

View File

@@ -0,0 +1,195 @@
/*
* 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_H264E_VEPU_V2_H__
#define __HAL_H264E_VEPU_V2_H__
#include "mpp_enc_cfg.h"
#include "h264e_syntax_new.h"
#include "mpp_rc.h"
typedef enum H264eVpuFrameType_t {
H264E_VPU_FRAME_P = 0,
H264E_VPU_FRAME_I = 1
} H264eVpuFrameType;
#define VEPU_CTRL_LEVELS 7
#define VEPU_CHECK_POINTS_MAX 10
typedef struct HalH264eVepuInput_t {
/* Hardware config format */
RK_S32 src_fmt;
RK_S32 src_w;
RK_S32 src_h;
size_t size_y;
size_t size_c;
RK_U32 offset_cb;
RK_U32 offset_cr;
RK_S32 r_mask_msb;
RK_S32 g_mask_msb;
RK_S32 b_mask_msb;
RK_U32 color_conversion_coeff_a;
RK_U32 color_conversion_coeff_b;
RK_U32 color_conversion_coeff_c;
RK_U32 color_conversion_coeff_e;
RK_U32 color_conversion_coeff_f;
} HalH264eVepuPrep;
typedef struct HalH264eVepuFrmAddr_t {
// original frame Y/Cb/Cr/RGB address
RK_U32 orig[3];
// reconstruction frame
RK_U32 recn[2];
RK_U32 refr[2];
} HalH264eVepuAddr;
/*
* Vepu buffer allocater
* There are three internal buffer for Vepu encoder:
* 1. cabac table input buffer
* 2. nal size table output buffer
* 3. recon / refer frame buffer
*/
typedef struct HalH264eVepuBufs_t {
MppBufferGroup group;
/* cabac table buffer */
RK_S32 cabac_init_idc;
MppBuffer cabac_table;
/*
* nal size table buffer
* table size must be 64-bit multiple, space for zero at the end of table
* Atleast 1 macroblock row in every slice
*/
RK_S32 mb_h;
RK_S32 nal_tab_size;
MppBuffer nal_size_table;
/*
* recon / refer frame buffer
* sync with encoder using slot index
*/
size_t frm_size;
size_t yuv_size;
RK_S32 frm_cnt;
MppBuffer frm_buf[H264E_MAX_REFS_CNT + 1];
} HalH264eVepuBufs;
typedef struct HalH264eVepuMbRc_t {
/* VEPU MB rate control parameter for config to hardware */
RK_S32 qp_init;
RK_S32 qp_min;
RK_S32 qp_max;
/*
* VEPU MB can have max 10 check points (cp).
*
* On each check point hardware will check the target bit and
* error bits and change qp according to delta qp step
*
* cp_distance_mbs check point distance in mbs (0 = disabled)
* cp_target bitrate target at each check point
* cp_error error bit level step for each delta qp
* cp_delta_qp delta qp applied on when on bit rate error amount
*/
RK_S32 cp_distance_mbs;
RK_S32 cp_target[VEPU_CHECK_POINTS_MAX];
RK_S32 cp_error[VEPU_CTRL_LEVELS];
RK_S32 cp_delta_qp[VEPU_CTRL_LEVELS];
/*
* MAD based QP adjustment
* mad_qp_change [-8..7]
* mad_threshold MAD threshold div256
*/
RK_S32 mad_qp_change;
RK_S32 mad_threshold;
/* slice split by mb row (0 = one slice) */
RK_S32 slice_size_mb_rows;
/* favor and penalty for mode decision */
/*
* VEPU MB rate control parameter which is read from hardware
* out_strm_size output stream size (bits)
* qp_sum QP Sum div2 output
* rlc_count RLC codeword count div4 output max 255*255*384/4
*/
RK_U32 out_strm_size;
RK_S32 qp_sum;
RK_S32 rlc_count;
RK_S32 cp_usage[VEPU_CHECK_POINTS_MAX];
/* Macroblock count with MAD value under threshold output */
RK_S32 less_mad_count;
/* MB count output */
RK_S32 mb_count;
/* hardware encoding status 0 - corret 1 - error */
RK_U32 hw_status;
} HalH264eVepuMbRc;
typedef void *HalH264eVepuMbRcCtx;
#ifdef __cplusplus
extern "C" {
#endif
/* buffer management function */
MPP_RET h264e_vepu_buf_init(HalH264eVepuBufs *bufs);
MPP_RET h264e_vepu_buf_deinit(HalH264eVepuBufs *bufs);
MPP_RET h264e_vepu_buf_set_cabac_idc(HalH264eVepuBufs *bufs, RK_S32 idc);
MPP_RET h264e_vepu_buf_set_frame_size(HalH264eVepuBufs *bufs, RK_S32 w, RK_S32 h);
MppBuffer h264e_vepu_buf_get_nal_size_table(HalH264eVepuBufs *bufs);
MppBuffer h264e_vepu_buf_get_frame_buffer(HalH264eVepuBufs *bufs, RK_S32 index);
/* preprocess setup function */
MPP_RET h264e_vepu_prep_setup(HalH264eVepuPrep *prep, MppEncPrepCfg *cfg);
MPP_RET h264e_vepu_prep_get_addr(HalH264eVepuPrep *prep, MppBuffer buffer,
RK_U32 (*addr)[3]);
/* macroblock bitrate control function */
MPP_RET h264e_vepu_mbrc_init(HalH264eVepuMbRcCtx *ctx, HalH264eVepuMbRc *mbrc);
MPP_RET h264e_vepu_mbrc_deinit(HalH264eVepuMbRcCtx ctx);
MPP_RET h264e_vepu_mbrc_setup(HalH264eVepuMbRcCtx ctx, MppEncCfgSet *cfg);
/*
* generate hardware MB rc config by:
* 1 - HalH264eVepuMbRcCtx ctx
* The previous frame encoding status
* 2 - RcSyntax
* Provide current frame target bitrate related info
* 3 - EncFrmStatus
* Provide dpb related info like I / P frame, temporal id, refer distance
*
* Then output the HalH264eVepuMbRc for register generation
*/
MPP_RET h264e_vepu_mbrc_prepare(HalH264eVepuMbRcCtx ctx, RcSyntax *rc,
EncFrmStatus *info, HalH264eVepuMbRc *mbrc);
MPP_RET h264e_vepu_mbrc_update(HalH264eVepuMbRcCtx ctx, HalH264eVepuMbRc *mbrc);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,36 @@
/*
* 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_H264E_VPU_TBL_H__
#define __HAL_H264E_VPU_TBL_H__
#include "rk_type.h"
#define H264E_CABAC_TABLE_BUF_SIZE (52*2*464)
/* H.264 motion estimation parameters */
extern const RK_U32 h264_prev_mode_favor[52];
/* sqrt(2^((qp-12)/3))*8 */
extern const RK_U32 h264_diff_mv_penalty[52];
/* 31*sqrt(2^((qp-12)/3))/4 */
extern const RK_U32 h264_diff_mv_penalty4p[52];
extern const RK_U32 h264_intra16_favor[52];
extern const RK_U32 h264_inter_favor[52];
extern const RK_U32 h264_skip_sad_penalty[52];
extern const RK_S32 h264_context_init_intra[460][2];
extern const RK_S32 h264_context_init[3][460][2];
#endif