diff --git a/mpp/codec/CMakeLists.txt b/mpp/codec/CMakeLists.txt index 0c26c305..857491ec 100644 --- a/mpp/codec/CMakeLists.txt +++ b/mpp/codec/CMakeLists.txt @@ -31,6 +31,7 @@ target_link_libraries(mpp_codec ${CODEC_H264E} ${CODEC_JPEGE} ${CODEC_H265E} + ${CODEC_VP8E} codec_dummy_enc codec_dummy_dec mpp_vproc diff --git a/mpp/codec/enc/CMakeLists.txt b/mpp/codec/enc/CMakeLists.txt index 66bf9fc2..7a855246 100644 --- a/mpp/codec/enc/CMakeLists.txt +++ b/mpp/codec/enc/CMakeLists.txt @@ -14,3 +14,7 @@ if(HAVE_H265E) add_subdirectory(h265) endif() +if(HAVE_VP8E) +add_subdirectory(vp8) +endif() + diff --git a/mpp/codec/enc/vp8/CMakeLists.txt b/mpp/codec/enc/vp8/CMakeLists.txt new file mode 100644 index 00000000..900d6429 --- /dev/null +++ b/mpp/codec/enc/vp8/CMakeLists.txt @@ -0,0 +1,22 @@ +include_directories(.) + +set(VP8E_API + ) +set(VP8E_COMMON + ) +set(VP8E_HDR + vp8e_debug.h + vp8e_rc.h) +set(VP8E_SRC + vp8e_api.c + vp8e_rc.c) + +add_library(codec_vp8e STATIC + ${VP8E_API} + ${VP8E_COMMON} + ${VP8E_HDR} + ${VP8E_SRC} + ) + +target_link_libraries(codec_vp8e mpp_base) +set_target_properties(codec_vp8e PROPERTIES FOLDER "mpp/codec") diff --git a/mpp/codec/enc/vp8/vp8e_api.c b/mpp/codec/enc/vp8/vp8e_api.c new file mode 100644 index 00000000..c44d2923 --- /dev/null +++ b/mpp/codec/enc/vp8/vp8e_api.c @@ -0,0 +1,235 @@ +/* + * 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 "vp8e_api" + +#include +#include + +#include "mpp_env.h" +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_rc.h" +#include "mpp_controller.h" + +#include "vp8e_api.h" +#include "vp8e_rc.h" +#include "vp8e_syntax.h" +#include "vp8e_debug.h" + +RK_U32 vp8e_rc_debug = 0; + +typedef struct { + /* config from mpp_enc */ + MppEncCfgSet *cfg; + MppEncCfgSet *set; + + /* internal rate control config*/ + RK_U32 rc_ready; + RK_U32 prep_ready; +// MppRateControl *rc; + Vp8eRc *rc; + + /* output to hal */ + RcSyntax syntax; + + RcHalResult result; + +} Vp8eCtx; + +MPP_RET vp8e_init(void *ctx, ControllerCfg *ctrl_cfg) +{ + MPP_RET ret = MPP_OK; + Vp8eCtx *p = (Vp8eCtx *)ctx; + + MppEncRcCfg *rc_cfg = &ctrl_cfg->cfg->rc; + MppEncPrepCfg *prep = &ctrl_cfg->cfg->prep; + + vp8e_rc_dbg_func("enter\n"); + if (NULL == ctx || NULL == ctrl_cfg) { + mpp_err_f("Init failed, contex or controller cfg is null!\n"); + ret = MPP_NOK; + goto __ERR_RET; + } + + p->cfg = ctrl_cfg->cfg; + p->set = ctrl_cfg->set; + + /* + * default prep: + * 720p + * YUV420SP + */ + prep->change = 0; + prep->width = 1280; + prep->height = 720; + prep->hor_stride = 1280; + prep->ver_stride = 720; +// prep->format = MPP_FMT_YUV420SP; + prep->rotation = MPP_ENC_ROT_0; + prep->mirroring = 0; + prep->denoise = 0; + + /* + * default rc_cfg: + * CBR + * 2Mbps +-25% + * 30fps + * gop 60 + */ + rc_cfg->change = 0; + rc_cfg->rc_mode = MPP_ENC_RC_MODE_CBR; + rc_cfg->quality = MPP_ENC_RC_QUALITY_MEDIUM; + rc_cfg->bps_target = 2000 * 1000; + rc_cfg->bps_max = rc_cfg->bps_target * 5 / 4; + rc_cfg->bps_min = rc_cfg->bps_target * 3 / 4; + rc_cfg->fps_in_flex = 0; + rc_cfg->fps_in_num = 30; + rc_cfg->fps_in_denorm = 1; + rc_cfg->fps_out_flex = 0; + rc_cfg->fps_out_num = 30; + rc_cfg->fps_out_denorm = 1; + rc_cfg->gop = 60; + rc_cfg->skip_cnt = 0; + + + p->rc = mpp_calloc(Vp8eRc, 1); + if (NULL == p->rc) { + mpp_err_f("failed to malloc vp8_rc\n"); + ret = MPP_ERR_MALLOC; + goto __ERR_RET; + } + + vp8e_init_rc(p->rc, ctrl_cfg->cfg); + + mpp_env_get_u32("vp8e_debug", &vp8e_rc_debug, 0); + + vp8e_rc_dbg_func("leave ret %d\n", ret); + return ret; + +__ERR_RET: + vp8e_rc_dbg_func("leave ret %d\n", ret); + return ret; +} + +MPP_RET vp8e_deinit(void *ctx) +{ + Vp8eCtx *p = (Vp8eCtx *)ctx; + + vp8e_rc_dbg_func("enter\n"); + if (p) { + if (p->rc) + mpp_free(p->rc); + mpp_free(p); + } + + vp8e_rc_dbg_func("leave\n"); + return MPP_OK; +} + +MPP_RET vp8e_encode(void *ctx, HalEncTask *task) +{ + Vp8eCtx *p = (Vp8eCtx *)ctx; + + RcSyntax *rc_syn = &p->syntax; + MppEncCfgSet *cfg = p->cfg; + + vp8e_rc_dbg_func("enter\n"); + + + vp8e_before_pic_rc(p->rc); + + if (rc_syn->bit_target <= 0) { + RK_S32 mb_width = MPP_ALIGN(cfg->prep.width, 16) >> 4; + RK_S32 mb_height = MPP_ALIGN(cfg->prep.height, 16) >> 4; + rc_syn->bit_target = mb_width * mb_height; + } + + task->syntax.data = p->rc; + task->syntax.number = 1; + task->valid = 1; + task->is_intra = p->rc->curr_frame_intra; + + vp8e_rc_dbg_func("leave\n"); + return MPP_OK; +} + +MPP_RET vp8e_reset(void *ctx) +{ + (void)ctx; + + return MPP_OK; +} + + +MPP_RET vp8e_flush(void *ctx) +{ + Vp8eCtx *p = (Vp8eCtx *)ctx; + (void)p; + + return MPP_OK; +} + +MPP_RET vp8e_config(void *ctx, RK_S32 cmd, void *param) +{ + MPP_RET ret = MPP_OK; + Vp8eCtx *p = (Vp8eCtx *)ctx; + + vp8e_rc_dbg_func("enter ctx %p cmd %x param %p\n", ctx, cmd, param); + switch (cmd) { + case MPP_ENC_SET_RC_CFG : { + vp8e_rc_dbg_cfg("update vp8e rc config"); + vp8e_update_rc_cfg(p->rc, &p->set->rc); + vp8e_init_rc(p->rc, p->set); + } break; + default: { + mpp_err("No correspond cmd found, and can not config!"); + ret = MPP_NOK; + } break; + } + + vp8e_rc_dbg_func("leave ret %d\n", ret); + return ret; +} + +MPP_RET vp8e_callback(void *ctx, void *feedback) +{ + vp8e_rc_dbg_func("enter\n"); + Vp8eCtx *p = (Vp8eCtx *)ctx; + Vp8eFeedback *fb = (Vp8eFeedback *)feedback; + RcHalResult *result = (RcHalResult *)fb->result; + + vp8e_after_pic_rc(p->rc, result->bits); + p->rc->curr_frame_intra = (result->type == INTRA_FRAME); + + vp8e_rc_dbg_func("leave\n"); + return MPP_OK; +} + +const ControlApi api_vp8e_controller = { + "vp8e_control", + MPP_VIDEO_CodingVP8, + sizeof(Vp8eCtx), + 0, + vp8e_init, + vp8e_deinit, + vp8e_encode, + vp8e_reset, + vp8e_flush, + vp8e_config, + vp8e_callback, +}; + diff --git a/mpp/codec/enc/vp8/vp8e_debug.h b/mpp/codec/enc/vp8/vp8e_debug.h new file mode 100644 index 00000000..0392746f --- /dev/null +++ b/mpp/codec/enc/vp8/vp8e_debug.h @@ -0,0 +1,40 @@ +/* + * 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 __VP8E_DEBUG_H__ +#define __VP8E_DEBUG_H__ + +#include "rk_type.h" + +#include "mpp_log.h" + +#define VP8E_DBG_RC_FUNCTION (0x00010000) +#define VP8E_DBG_RC_BPS (0x00020000) +#define VP8E_DBG_RC (0x00040000) +#define VP8E_DBG_RC_CFG (0x00080000) + +#define VP8E_DBG(flag, fmt, ...) _mpp_dbg(vp8e_rc_debug, flag, fmt, ## __VA_ARGS__) +#define VP8E_DBG_F(flag, fmt, ...) _mpp_dbg_f(vp8e_rc_debug, flag, fmt, ## __VA_ARGS__) + + +#define vp8e_rc_dbg_func(fmt, ...) VP8E_DBG_F(VP8E_DBG_RC_FUNCTION, fmt, ## __VA_ARGS__) +#define vp8e_rc_dbg_bps(fmt, ...) VP8E_DBG(VP8E_DBG_RC_BPS, fmt, ## __VA_ARGS__) +#define vp8e_rc_dbg_rc(fmt, ...) VP8E_DBG(VP8E_DBG_RC, fmt, ## __VA_ARGS__) +#define vp8e_rc_dbg_cfg(fmt, ...) VP8E_DBG(VP8E_DBG_RC_CFG, fmt, ## __VA_ARGS__) + +extern RK_U32 vp8e_rc_debug; + +#endif //__VP8E_DEBUG_H__ diff --git a/mpp/codec/enc/vp8/vp8e_rc.c b/mpp/codec/enc/vp8/vp8e_rc.c new file mode 100644 index 00000000..669b1b2c --- /dev/null +++ b/mpp/codec/enc/vp8/vp8e_rc.c @@ -0,0 +1,559 @@ +/* + * 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 "vp8e_rc" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_rc.h" + +#include "vp8e_syntax.h" +#include "vp8e_debug.h" +#include "vp8e_rc.h" + +#define DSCY 64 +#define UPSCALE 8000 +#define I32_MPP_MAX 0x7fffffff +#define QINDEX_RANGE 128 +#define RC_ERROR_RESET 0x7fffffff +#define BIT_COUNT_MAX 0x1fffffff +#define BIT_COUNT_MIN (-BIT_COUNT_MAX) + +static const RK_S32 ac_q_lookup_tbl[QINDEX_RANGE] = { + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 60, 62, 64, 66, 68, + 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, + 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, + 110, 112, 114, 116, 119, 122, 125, 128, 131, 134, + 137, 140, 143, 146, 149, 152, 155, 158, 161, 164, + 167, 170, 173, 177, 181, 185, 189, 193, 197, 201, + 205, 209, 213, 217, 221, 225, 229, 234, 239, 245, + 249, 254, 259, 264, 269, 274, 279, 284 +}; + +static RK_S32 initial_qp(RK_S32 bits, RK_S32 pels) +{ + RK_S32 i = -1; + static const RK_S32 qp_tbl[2][12] = { + {47, 57, 73, 93, 122, 155, 214, 294, 373, 506, 781, 0x7FFFFFFF}, + {120, 110, 100, 90, 80, 70, 60, 50, 40, 30, 20, 10} + }; + + if (bits > 1000000) + return 10; + + pels >>= 8; + bits >>= 5; + + bits *= pels + 250; + bits /= 350 + (3 * pels) / 4; + bits = axb_div_c(bits, UPSCALE, pels << 6); + + while (qp_tbl[0][++i] < bits); + + return qp_tbl[1][i]; +} + +static MPP_RET update_rc_error(Vp8eLinReg *p, RK_S32 bits) +{ + p->len = 3; + + if (bits >= (RK_S32)I32_MPP_MAX) { + p->bits[0] = 0; + p->bits[1] = 0; + p->bits[2] = 0; + return MPP_NOK; + } + + p->bits[0] = bits - p->bits[2]; + p->bits[1] = bits + p->bits[1]; + p->bits[2] = bits; + + return MPP_OK; +} + +static RK_S32 lin_sxy(RK_S32 *qp, RK_S32 *r, RK_S32 n) +{ + RK_S32 tmp, sum = 0; + + while (n--) { + tmp = qp[n] * qp[n] * qp[n]; + if (tmp > r[n]) { + sum += MPP_DIV_SIGN(tmp, DSCY) * r[n]; + } else { + sum += tmp * MPP_DIV_SIGN(r[n], DSCY); + } + + if (sum < 0) { + return I32_MPP_MAX; + } + } + + return sum; +} + +static RK_S32 lin_sx(RK_S32 *qp, RK_S32 n) +{ + RK_S32 tmp = 0; + + while (n--) { + tmp += qp[n]; + } + + return tmp; +} + +static RK_S32 lin_sy(RK_S32 *qp, RK_S32 *r, RK_S32 n) +{ + RK_S32 sum = 0; + + while (n--) { + sum += qp[n] * qp[n] * r[n]; + if (sum < 0) { + return 2147483647 / 64; + } + } + + return MPP_DIV_SIGN(sum, DSCY); +} + +static RK_S32 lin_nsxx(RK_S32 *qp, RK_S32 n) +{ + RK_S32 tmp = 0; + RK_S32 sum = 0; + RK_S32 d = n; + + while (n--) { + tmp = qp[n]; + tmp *= tmp; + sum += d * tmp; + } + + return sum; +} + +static void update_model(Vp8eLinReg *p) +{ + RK_S32 a1, a2; + + RK_S32 *qs = p->qs; + RK_S32 *r = p->bits; + RK_S32 n = p->len; + RK_S32 sx = lin_sx(qs, n); + RK_S32 sy = lin_sy(qs, r, n); + + a1 = lin_sxy(qs, r, n); + a1 = (a1 < (I32_MPP_MAX / n)) ? (a1 * n) : I32_MPP_MAX; + + if (sy == 0) { + a1 = 0; + } else { + a1 -= (sx < I32_MPP_MAX / sy) ? (sx * sy) : I32_MPP_MAX; + } + + a2 = (lin_nsxx(qs, n) - (sx * sx)); + if (a2 == 0) { + if (p->a1 == 0) { + a1 = 0; + } else { + a1 = (p->a1 * 2) / 3; + } + } else { + a1 = axb_div_c(a1, DSCY, a2); + } + + a1 = MPP_MAX(a1, -4096 * DSCY); + a1 = MPP_MIN(a1, 4096 * DSCY - 1); + + a2 = MPP_DIV_SIGN(sy * DSCY, n) - MPP_DIV_SIGN(a1 * sx, n); + + if (p->len > 0) { + p->a1 = a1; + p->a2 = a2; + } + +} + +static RK_S32 get_vir_buffer_bitcnt(Vp8eVirBuf *vb, RK_S32 time_inc) +{ + RK_S32 drift = 0; + RK_S32 target = 0; + + /* Saturate realBitCnt, this is to prevent overflows caused by much greater + bitrate setting than is really possible to reach */ + if (vb->real_bit_cnt > BIT_COUNT_MAX) + vb->real_bit_cnt = BIT_COUNT_MAX; + if (vb->real_bit_cnt < BIT_COUNT_MIN) + vb->real_bit_cnt = BIT_COUNT_MIN; + + vb->pic_time_inc += time_inc; + vb->virtual_bit_cnt += axb_div_c(vb->bit_rate, time_inc, + vb->time_scale); + target = vb->virtual_bit_cnt - vb->real_bit_cnt; + + /* Saturate target, prevents rc going totally out of control. + This situation should never happen. */ + if (target > BIT_COUNT_MAX) + target = BIT_COUNT_MAX; + if (target < BIT_COUNT_MIN) + target = BIT_COUNT_MIN; + + while (vb->pic_time_inc >= vb->time_scale) { + vb->pic_time_inc -= vb->time_scale; + vb->virtual_bit_cnt -= vb->bit_rate; + vb->real_bit_cnt -= vb->bit_rate; + } + + drift = axb_div_c(vb->bit_rate, vb->pic_time_inc, vb->time_scale); + drift -= vb->virtual_bit_cnt; + vb->virtual_bit_cnt += drift; + + return target; +} + +static MPP_RET skip_pic(Vp8eRc *rc) +{ + Vp8eVirBuf *vb = &rc->virbuf; + RK_S32 skip_inc_limit = -vb->bit_per_pic / 3; + RK_S32 skip_dec_limit = vb->bit_per_pic / 3; + RK_S32 bit_available = vb->virtual_bit_cnt - vb->real_bit_cnt; + + if (((rc->pic_rc_enable == 0) || (vb->skip_frame_target == 0)) && + (bit_available < skip_inc_limit)) + vb->skip_frame_target++; + + if ((bit_available > skip_dec_limit) && vb->skip_frame_target > 0) + vb->skip_frame_target--; + + if (vb->skipped_frames < vb->skip_frame_target) { + vb->skipped_frames++; + rc->frame_coded = 0; + } else { + vb->skipped_frames = 0; + } + + return MPP_OK; +} + +static RK_S32 new_pic_quant(Vp8eLinReg *p, RK_S32 bits, RK_U8 use_qp_delta_limit) +{ + RK_S32 tmp, diff; + RK_S32 qp = p->qp_prev; + RK_S32 qp_best = p->qp_prev; + RK_S32 diff_best = I32_MPP_MAX; + + if (p->a1 == 0 && p->a2 == 0) { + return qp; + } + + if (bits <= 0) { + if (use_qp_delta_limit) + qp = MPP_MIN(QINDEX_RANGE - 1, MPP_MAX(0, qp + 4)); + else + qp = MPP_MIN(QINDEX_RANGE - 1, MPP_MAX(0, qp + 10)); + + return qp; + } + + do { + tmp = MPP_DIV_SIGN(p->a1, ac_q_lookup_tbl[qp]); + tmp += MPP_DIV_SIGN(p->a2, ac_q_lookup_tbl[qp] * ac_q_lookup_tbl[qp]); + diff = MPP_ABS(tmp - bits); + + if (diff < diff_best) { + diff_best = diff; + qp_best = qp; + if ((tmp - bits) <= 0) { + if (qp < 1) { + break; + } + qp--; + } else { + if (qp >= QINDEX_RANGE - 1) { + break; + } + qp++; + } + } else { + break; + } + } while ((qp >= 0) && (qp < QINDEX_RANGE)); + qp = qp_best; + + if (use_qp_delta_limit) { + tmp = qp - p->qp_prev; + if (tmp > 4) { + qp = p->qp_prev + 4; + } else if (tmp < -4) { + qp = p->qp_prev - 4; + } + } + + return qp; +} + +static RK_S32 avg_rc_error(Vp8eLinReg *p) +{ + return MPP_DIV_SIGN(p->bits[2] * 4 + p->bits[1] * 6 + p->bits[0] * 0, 100); +} + +static MPP_RET cal_pic_quant(Vp8eRc *rc) +{ + RK_S32 tmp = 0; + RK_S32 tmp_value = 0; + RK_S32 tmp_avg_rc_error; + RK_U8 use_qp_delta_limit = 1; + + if (!rc->pic_rc_enable) { + rc->qp_hdr = rc->fixed_qp; + return MPP_OK; + } + + if (rc->curr_frame_intra) { + if (rc->gop_len == 1 || rc->gop_len == 2) { + tmp = new_pic_quant(&rc->lin_reg, + axb_div_c(rc->target_pic_size, 256, rc->mb_per_pic), + use_qp_delta_limit); + } else { + if (rc->gop_qp_sum) { + tmp = MPP_DIV_SIGN(rc->gop_qp_sum, rc->gop_qp_div); + } + rc->gop_qp_sum = 0; + rc->gop_qp_div = 0; + } + if (tmp) { + rc->qp_hdr = tmp; + } + } else if (rc->prev_frame_intra) { + rc->qp_hdr = rc->qp_hdr_prev; + } else { + tmp_avg_rc_error = avg_rc_error(&rc->r_error); + tmp_value = axb_div_c(rc->target_pic_size - tmp_avg_rc_error, + 256, rc->mb_per_pic); + rc->qp_hdr = new_pic_quant(&rc->lin_reg, tmp_value, + use_qp_delta_limit); + } + + vp8e_rc_dbg_rc("frame_cnt = %d, qp = %d\n", rc->frame_cnt, rc->qp_hdr); + + rc->qp_hdr = MPP_MIN(rc->qp_max, MPP_MAX(rc->qp_min, rc->qp_hdr)); + rc->qp_hdr_prev = rc->qp_hdr; + + if (rc->curr_frame_intra) { + if (rc->fixed_intra_qp) + rc->qp_hdr = rc->fixed_intra_qp; + else if (!rc->prev_frame_intra) + rc->qp_hdr += rc->intra_qp_delta; + + rc->qp_hdr = MPP_MIN(rc->qp_max, MPP_MAX(rc->qp_min, rc->qp_hdr)); + } else { + rc->gop_qp_sum += rc->qp_hdr; + rc->gop_qp_div++; + } + + return MPP_OK; +} + +static void update_tables(Vp8eLinReg *p, RK_S32 qp, RK_S32 bits) +{ + RK_S32 len = 10; + RK_S32 tmp = p->pos; + + p->qp_prev = qp; + p->qs[tmp] = ac_q_lookup_tbl[qp]; + p->bits[tmp] = bits; + + if ((++p->pos) >= len) { + p->pos = 0; + } + + if (p->len < len) { + p->len++; + } +} + +MPP_RET vp8e_update_rc_cfg(Vp8eRc *rc, MppEncRcCfg *cfg) +{ + RK_U32 change = cfg->change; + Vp8eVirBuf *vb = &rc->virbuf; + + if (change & MPP_ENC_RC_CFG_CHANGE_BPS) { + vp8e_rc_dbg_cfg("bps: %d [%d %d]\n", + cfg->bps_target, cfg->bps_min, cfg->bps_max); + vb->bps_min = cfg->bps_min; + vb->bps_max = cfg->bps_max; + vb->bit_rate = cfg->bps_target; + } + + if (change & MPP_ENC_RC_CFG_CHANGE_FPS_OUT) { + vp8e_rc_dbg_cfg("fps: %d / %d\n", cfg->fps_out_num, cfg->fps_out_denorm); + rc->fps_out_num = cfg->fps_out_num; + rc->fps_out_denorm = cfg->fps_out_denorm; + if (rc->fps_out_denorm == 0) { + mpp_err("denorm can not be 0, change to default 1"); + rc->fps_out_denorm = 1; + } + rc->fps_out = rc->fps_out_num / rc->fps_out_denorm; + if (rc->fps_out == 0) { + rc->fps_out = 30; + rc->fps_out_num = 30; + rc->fps_out_denorm = 1; + mpp_err("fps out can not be 0, change to default 30"); + } + } + + if ((change & MPP_ENC_RC_CFG_CHANGE_GOP) && + (rc->gop_len != cfg->gop)) { + rc->gop_len = cfg->gop; + vp8e_rc_dbg_cfg("gop: %d\n", cfg->gop); + } + vb->bit_per_pic = axb_div_c(vb->bit_rate, rc->fps_out_denorm, rc->fps_out_num); + + cfg->change = 0; + + return MPP_OK; +} + + +MPP_RET vp8e_init_rc(Vp8eRc *rc, MppEncCfgSet *cfg) +{ + RK_S32 max_bps; + Vp8eVirBuf *vb = &rc->virbuf; + + rc->qp_hdr = -1; + rc->qp_min = 0; + rc->qp_max = QINDEX_RANGE; + rc->pic_skip = 0; + rc->pic_rc_enable = 1; + rc->gop_len = cfg->rc.gop; + rc->intra_qp_delta = 0; + rc->fixed_intra_qp = 0; + rc->intra_picture_rate = 30; + rc->golden_picture_rate = 0; + rc->altref_picture_rate = 0; + rc->virbuf.bit_rate = cfg->rc.bps_target; + rc->fps_out_denorm = cfg->rc.fps_out_denorm; + rc->fps_out_num = cfg->rc.fps_out_num; + rc->mb_per_pic = ((cfg->prep.width + 15) / 16) * ((cfg->prep.height + 15) / 16); + + if (rc->qp_max >= QINDEX_RANGE) + rc->qp_max = QINDEX_RANGE - 1; + + if (rc->qp_min < 0) + rc->qp_min = 0; + + max_bps = rc->mb_per_pic * 16 * 16 * 6; + max_bps = axb_div_c(max_bps, rc->fps_out_num, + rc->fps_out_denorm); + + if (max_bps < 0) + max_bps = I32_MPP_MAX; + vb->bit_rate = MPP_MIN(vb->bit_rate, max_bps); + vb->bit_per_pic = axb_div_c(vb->bit_rate, rc->fps_out_denorm, + rc->fps_out_num); + + if (rc->qp_hdr == -1) + rc->qp_hdr = initial_qp(vb->bit_per_pic, rc->mb_per_pic * 16 * 16); + + rc->qp_hdr = MPP_MIN(rc->qp_max, MPP_MAX(rc->qp_min, rc->qp_hdr)); + vp8e_rc_dbg_rc("init qp, qp = %d, bitRate = %d, bitPerPic = %d\n", + rc->qp_hdr, vb->bit_rate, vb->bit_per_pic); + + rc->qp_hdr_prev = rc->qp_hdr; + rc->fixed_qp = rc->qp_hdr; + rc->frame_coded = 1; + rc->curr_frame_intra = 1; + rc->prev_frame_intra = 0; + rc->frame_cnt = 0; + rc->gop_qp_sum = 0; + rc->gop_qp_div = 0; + rc->target_pic_size = 0; + rc->frame_bit_cnt = 0; + rc->time_inc = 0; + + memset(&rc->lin_reg, 0, sizeof(rc->lin_reg)); + rc->lin_reg.qs[0] = ac_q_lookup_tbl[QINDEX_RANGE - 1]; + rc->lin_reg.qp_prev = rc->qp_hdr; + + vb->gop_rem = rc->gop_len; + vb->time_scale = rc->fps_out_num; + + update_rc_error(&rc->r_error, RC_ERROR_RESET); + + return MPP_OK; +} + +MPP_RET vp8e_before_pic_rc(Vp8eRc *rc) +{ + RK_S32 tmp = 0; + Vp8eVirBuf *vb = &rc->virbuf; + + rc->frame_coded = 1; + + if (rc->curr_frame_intra || vb->gop_rem == 1) { + vb->gop_rem = rc->gop_len; + } else { + vb->gop_rem--; + } + + tmp = get_vir_buffer_bitcnt(&rc->virbuf, (RK_S32)rc->time_inc); + + rc->target_pic_size = vb->bit_per_pic + + MPP_DIV_SIGN(tmp, MPP_MAX(vb->gop_rem, 3)); + rc->target_pic_size = MPP_MAX(0, rc->target_pic_size); + + if (rc->pic_skip) + skip_pic(rc); + + cal_pic_quant(rc); + + return MPP_OK; +} + +MPP_RET vp8e_after_pic_rc(Vp8eRc *rc, RK_S32 bitcnt) +{ + Vp8eVirBuf *vb = &rc->virbuf; + + rc->time_inc = 1; + rc->frame_cnt++; + rc->frame_bit_cnt = bitcnt; + rc->prev_frame_intra = rc->curr_frame_intra; + vb->real_bit_cnt += bitcnt; + + if ((!rc->curr_frame_intra) || (rc->gop_len == 1)) { + update_tables(&rc->lin_reg, rc->qp_hdr_prev, + axb_div_c(bitcnt, 256, rc->mb_per_pic)); + + + if (vb->gop_rem == rc->gop_len - 1) { + update_rc_error(&rc->r_error, RC_ERROR_RESET); + } else { + update_rc_error(&rc->r_error, + MPP_MIN(bitcnt - rc->target_pic_size, + 2 * rc->target_pic_size)); + } + update_model(&rc->lin_reg); + } + + return MPP_OK; +} diff --git a/mpp/codec/enc/vp8/vp8e_rc.h b/mpp/codec/enc/vp8/vp8e_rc.h new file mode 100644 index 00000000..305bc785 --- /dev/null +++ b/mpp/codec/enc/vp8/vp8e_rc.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 __VP8E_RC_H__ +#define __VP8E_RC_H__ + +#include "rk_mpi.h" + +#include "vp8e_syntax.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vp8e_init_rc(Vp8eRc *rc, MppEncCfgSet *cfg); +MPP_RET vp8e_update_rc_cfg(Vp8eRc *rc, MppEncRcCfg *cfg); +MPP_RET vp8e_before_pic_rc(Vp8eRc *rc); +MPP_RET vp8e_after_pic_rc(Vp8eRc *rc, RK_S32 bitcnt); + +#ifdef __cplusplus +} +#endif + + +#endif //__VP8E_RC_H__ diff --git a/mpp/codec/inc/vp8e_api.h b/mpp/codec/inc/vp8e_api.h index 546a72c4..54ed2df7 100644 --- a/mpp/codec/inc/vp8e_api.h +++ b/mpp/codec/inc/vp8e_api.h @@ -17,6 +17,16 @@ #ifndef __VP8E_API_H__ #define __VP8E_API_H__ +#include "encoder_codec_api.h" +#ifdef __cplusplus +extern "C" { +#endif -#endif /*__VP8E_API_H__*/ \ No newline at end of file +extern const ControlApi api_vp8e_controller; + +#ifdef __cplusplus +} +#endif + +#endif /*__VP8E_API_H__*/ diff --git a/mpp/codec/mpp_controller.cpp b/mpp/codec/mpp_controller.cpp index 51e918a2..b40259b2 100644 --- a/mpp/codec/mpp_controller.cpp +++ b/mpp/codec/mpp_controller.cpp @@ -23,6 +23,7 @@ #include "h264e_api.h" #include "jpege_api.h" #include "h265e_api.h" +#include "vp8e_api.h" #include "mpp_controller.h" /* @@ -38,6 +39,9 @@ static const ControlApi *controllers[] = { #if HAVE_H265E &api_h265e_controller, #endif +#if HAVE_VP8E + &api_vp8e_controller, +#endif }; typedef struct ControllerImpl_t { diff --git a/mpp/codecs.cmake b/mpp/codecs.cmake index 872f43ab..347bfbd3 100644 --- a/mpp/codecs.cmake +++ b/mpp/codecs.cmake @@ -108,3 +108,12 @@ if( ENABLE_H265E ) set(HAL_H265E hal_h265e) add_definitions(-DHAVE_H265E) endif() + +# vp8 encoder +option(ENABLE_VP8E "Enable vp8 encoder" ON) +if( ENABLE_VP8E ) + set(HAVE_VP8E true) + set(CODEC_VP8E codec_vp8e) + set(HAL_VP8E hal_vp8e) + add_definitions(-DHAVE_VP8E) +endif() diff --git a/mpp/common/vp8e_syntax.h b/mpp/common/vp8e_syntax.h new file mode 100644 index 00000000..f0b4b40d --- /dev/null +++ b/mpp/common/vp8e_syntax.h @@ -0,0 +1,103 @@ +/* + * 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 __VP8E_SYNTAX_H__ +#define __VP8E_SYNTAX_H__ + +#include "rk_type.h" + +typedef struct { + RK_S32 a1; + RK_S32 a2; + RK_S32 qp_prev; + RK_S32 qs[15]; + RK_S32 bits[15]; + RK_S32 pos; + RK_S32 len; + RK_S32 zero_div; +} Vp8eLinReg; + + +typedef struct vp8e_feedback_t { + /* rc */ + void *result; + RK_U32 hw_status; /* 0:corret, 1:error */ + + RK_S32 qp_sum; + RK_S32 cp[10]; + RK_S32 mad_count; + RK_S32 rlc_count; + RK_U32 out_strm_size; + RK_U32 out_hw_strm_size; + RK_S64 sse_sum; + +} Vp8eFeedback; + +typedef struct vp8e_virture_buffer_t { + RK_S32 buffer_size; + RK_S32 bit_rate; //MppEncRcCfg.bps_target + RK_S32 bps_max; + RK_S32 bps_min; + RK_S32 bit_per_pic; + RK_S32 pic_time_inc; + RK_S32 time_scale; + RK_S32 units_in_tic; + RK_S32 virtual_bit_cnt; + RK_S32 real_bit_cnt; + RK_S32 buffer_occupancy; + RK_S32 skip_frame_target; + RK_S32 skipped_frames; + RK_S32 bucket_fullness; + RK_S32 gop_rem; +} Vp8eVirBuf; + +typedef struct { + RK_U8 pic_rc_enable; + RK_U8 pic_skip; + RK_U8 frame_coded; + RK_S32 mb_per_pic; + RK_S32 mb_rows; + RK_S32 curr_frame_intra; + RK_S32 prev_frame_intra; + RK_S32 fixed_qp; + RK_S32 qp_hdr; + RK_S32 qp_min; + RK_S32 qp_max; + RK_S32 qp_hdr_prev; + RK_S32 fps_out_num; //MppEncRcCfg.fps_out_num + RK_S32 fps_out_denorm; //MppEncRcCfg.fps_out_denorm + RK_S32 fps_out; + + RK_S32 target_pic_size; + RK_S32 frame_bit_cnt; + RK_S32 gop_qp_sum; + RK_S32 gop_qp_div; + RK_S32 frame_cnt; + RK_S32 gop_len; + RK_S32 intra_qp_delta; + RK_S32 fixed_intra_qp; + RK_S32 mb_qp_adjustment; + RK_S32 intra_picture_rate; + RK_S32 golden_picture_rate; + RK_S32 altref_picture_rate; + RK_U32 time_inc; + + Vp8eLinReg lin_reg; + Vp8eLinReg r_error; + Vp8eVirBuf virbuf; +} Vp8eRc; + +#endif /*__VP8E_SYNTAX_H__*/ diff --git a/mpp/hal/CMakeLists.txt b/mpp/hal/CMakeLists.txt index 611e17cc..1ad5b5e5 100644 --- a/mpp/hal/CMakeLists.txt +++ b/mpp/hal/CMakeLists.txt @@ -41,6 +41,7 @@ target_link_libraries(mpp_hal ${HAL_H264E} ${HAL_JPEGE} ${HAL_H265E} + ${HAL_VP8E} hal_dummy mpp_device ) diff --git a/mpp/hal/inc/hal_vp8e_api.h b/mpp/hal/inc/hal_vp8e_api.h new file mode 100644 index 00000000..5ffe0d22 --- /dev/null +++ b/mpp/hal/inc/hal_vp8e_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_VP8E_API_H__ +#define __HAL_VP8E_API_H__ + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_api_vp8e; + +#ifdef __cplusplus +} +#endif + +#endif /* __HAL_VP8E_API_H__ */ diff --git a/mpp/hal/mpp_hal.cpp b/mpp/hal/mpp_hal.cpp index 5d38122e..ea16b399 100644 --- a/mpp/hal/mpp_hal.cpp +++ b/mpp/hal/mpp_hal.cpp @@ -36,6 +36,7 @@ #include "hal_jpegd_api.h" #include "hal_jpege_api.h" #include "hal_h265e_api.h" +#include "hal_vp8e_api.h" // for test and demo #include "hal_dummy_dec_api.h" @@ -80,6 +81,9 @@ static const MppHalApi *hw_apis[] = { #endif #if HAVE_H265E &hal_api_h265e, +#endif +#if HAVE_VP8E + &hal_api_vp8e, #endif &hal_api_dummy_dec, &hal_api_dummy_enc, diff --git a/mpp/hal/vpu/CMakeLists.txt b/mpp/hal/vpu/CMakeLists.txt index 945b399a..b17429f5 100644 --- a/mpp/hal/vpu/CMakeLists.txt +++ b/mpp/hal/vpu/CMakeLists.txt @@ -27,3 +27,7 @@ endif() if( HAVE_H264E ) add_subdirectory(h264e) endif() + +if( HAVE_VP8E) + add_subdirectory(vp8e) +endif() \ No newline at end of file diff --git a/mpp/hal/vpu/vp8e/CMakeLists.txt b/mpp/hal/vpu/vp8e/CMakeLists.txt new file mode 100644 index 00000000..9d65b1a4 --- /dev/null +++ b/mpp/hal/vpu/vp8e/CMakeLists.txt @@ -0,0 +1,28 @@ +include_directories(.) + +set(HAL_VP8E_HDR + hal_vp8e_debug.h + hal_vp8e_table.h + hal_vp8e_entropy.h + hal_vp8e_putbit.h + hal_vp8e_base.h + hal_vp8e_vepu1.h + hal_vp8e_vepu2.h + hal_vp8e_vepu1_reg.h + hal_vp8e_vepu2_reg.h + ) + +set(HAL_VP8E_SRC + hal_vp8e_api.c + hal_vp8e_putbit.c + hal_vp8e_table.c + hal_vp8e_entropy.c + hal_vp8e_base.c + hal_vp8e_vepu1.c + hal_vp8e_vepu2.c + ) + +add_library(hal_vp8e STATIC ${HAL_VP8E_SRC}) + +set_target_properties(hal_vp8e PROPERTIES FOLDER "mpp/hal") +target_link_libraries(hal_vp8e mpp_base) diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_api.c b/mpp/hal/vpu/vp8e/hal_vp8e_api.c new file mode 100644 index 00000000..3c9d43e6 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_api.c @@ -0,0 +1,155 @@ +/* + * 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_vp8e_api" + +#include + +#include "mpp_env.h" +#include "mpp_log.h" +#include "mpp_common.h" + +#include "mpp_hal.h" +#include "mpp_platform.h" + +#include "hal_vp8e_base.h" +#include "hal_vp8e_vepu1.h" +#include "hal_vp8e_vepu2.h" +#include "hal_vp8e_debug.h" + +RK_U32 vp8e_hal_debug = 0; + +static MPP_RET hal_vp8e_gen_regs(void *hal, HalTaskInfo *task) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + ctx->rc = (Vp8eRc *)task->enc.syntax.data; + + return ctx->hal_api.reg_gen(ctx, task); +} + +static MPP_RET hal_vp8e_start(void *hal, HalTaskInfo *task) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + return ctx->hal_api.start(ctx, task); +} + +static MPP_RET hal_vp8e_wait(void *hal, HalTaskInfo *task) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + return ctx->hal_api.wait(ctx, task); +} + +static MPP_RET hal_vp8e_reset(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + return ctx->hal_api.reset(ctx); +} + +static MPP_RET hal_vp8e_flush(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + return ctx->hal_api.flush(ctx); +} + +static MPP_RET hal_vp8e_control(void *hal, RK_S32 cmd_type, void *param) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + return ctx->hal_api.control(ctx, cmd_type, param); +} + +static MPP_RET hal_vp8e_deinit(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + return ctx->hal_api.deinit(ctx); +} + +static MPP_RET hal_vp8e_init(void *hal, MppHalCfg *cfg) +{ + MppHalApi *p_api = NULL; + VpuHardMode hard_mode = MODE_NULL; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + if (ctx == NULL) + return MPP_ERR_VALUE; + memset(ctx, 0, sizeof(HalVp8eCtx)); + + mpp_env_get_u32("vp8e_debug", &vp8e_hal_debug, 0); + + p_api = &ctx->hal_api; + { + RK_U32 hw_flag = mpp_get_vcodec_type(); + if (hw_flag & HAVE_VPU2) + hard_mode = VDPU2_MODE; + else if (hw_flag & HAVE_VPU1) + hard_mode = VDPU1_MODE; + else { + mpp_err_f("Failed to init due to unsupported hard mode, hw_flag = %d\n", hw_flag); + return MPP_ERR_INIT; + } + } + switch (hard_mode) { + case VDPU2_MODE: + p_api->init = hal_vp8e_vepu2_init; + p_api->deinit = hal_vp8e_vepu2_deinit; + p_api->reg_gen = hal_vp8e_vepu2_gen_regs; + p_api->start = hal_vp8e_vepu2_start; + p_api->wait = hal_vp8e_vepu2_wait; + p_api->reset = hal_vp8e_vepu2_reset; + p_api->flush = hal_vp8e_vepu2_flush; + p_api->control = hal_vp8e_vepu2_control; + break; + case VDPU1_MODE: + p_api->init = hal_vp8e_vepu1_init; + p_api->deinit = hal_vp8e_vepu1_deinit; + p_api->reg_gen = hal_vp8e_vepu1_gen_regs; + p_api->start = hal_vp8e_vepu1_start; + p_api->wait = hal_vp8e_vepu1_wait; + p_api->reset = hal_vp8e_vepu1_reset; + p_api->flush = hal_vp8e_vepu1_flush; + p_api->control = hal_vp8e_vepu1_control; + break; + default: + break; + } + + ctx->cfg = cfg->cfg; + ctx->set = cfg->set; + + return p_api->init(ctx, cfg); +} + +const MppHalApi hal_api_vp8e = { + .name = "vp8e", + .type = MPP_CTX_ENC, + .coding = MPP_VIDEO_CodingVP8, + .ctx_size = sizeof(HalVp8eCtx), + .flag = 0, + .init = hal_vp8e_init, + .deinit = hal_vp8e_deinit, + .reg_gen = hal_vp8e_gen_regs, + .start = hal_vp8e_start, + .wait = hal_vp8e_wait, + .reset = hal_vp8e_reset, + .flush = hal_vp8e_flush, + .control = hal_vp8e_control, +}; + diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_base.c b/mpp/hal/vpu/vp8e/hal_vp8e_base.c new file mode 100644 index 00000000..d2d73eff --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_base.c @@ -0,0 +1,1701 @@ +/* + * 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_vp8e_base" + +#include + +#include "mpp_log.h" +#include "mpp_hal.h" +#include "mpp_buffer.h" +#include "mpp_common.h" + +#include "hal_vp8e_base.h" +#include "hal_vp8e_putbit.h" +#include "hal_vp8e_table.h" +#include "hal_vp8e_debug.h" + +static MPP_RET set_frame_params(void *hal) +{ + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + { + RK_S32 i; + Pps *pps = ctx->ppss.pps; + Vp8eSps *sps = &ctx->sps; + + for (i = 0; i < 4; i++) { + pps->qp_sgm[i] = ctx->rc->qp_hdr; + pps->level_sgm[i] = sps->filter_level; + } + } + + return MPP_OK; +} + +static MPP_RET set_filter(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eSps *sps = &ctx->sps; + + if (sps->auto_filter_level) { + RK_U32 qp = 36; + Pps *p_pps = ctx->ppss.pps; + if (ctx->frame_type == VP8E_FRM_KEY) { + RK_S32 tmp = (qp * 64) / 128 + 8; + sps->filter_level = MPP_CLIP3(0, 63, tmp); + p_pps->level_sgm[0] = MPP_CLIP3(0, 63, (p_pps->qp_sgm[0] * 64) / 128 + 8); + p_pps->level_sgm[1] = MPP_CLIP3(0, 63, (p_pps->qp_sgm[1] * 64) / 128 + 8); + p_pps->level_sgm[2] = MPP_CLIP3(0, 63, (p_pps->qp_sgm[2] * 64) / 128 + 8); + p_pps->level_sgm[3] = MPP_CLIP3(0, 63, (p_pps->qp_sgm[3] * 64) / 128 + 8); + } else { + sps->filter_level = inter_level_tbl[qp]; + p_pps->level_sgm[0] = inter_level_tbl[p_pps->qp_sgm[0]]; + p_pps->level_sgm[1] = inter_level_tbl[p_pps->qp_sgm[1]]; + p_pps->level_sgm[2] = inter_level_tbl[p_pps->qp_sgm[2]]; + p_pps->level_sgm[3] = inter_level_tbl[p_pps->qp_sgm[3]]; + } + } + + if (sps->auto_filter_sharpness) { + sps->filter_sharpness = 0; + } + + if (!sps->filter_delta_enable) + return MPP_NOK; + + if (sps->filter_delta_enable == 2) { + sps->filter_delta_enable = 1; + return MPP_NOK; + } + + if (sps->filter_level == 0) { + sps->ref_delta[0] = 0; /* Intra frame */ + sps->ref_delta[1] = 0; /* Last frame */ + sps->ref_delta[2] = 0; /* Golden frame */ + sps->ref_delta[3] = 0; /* Altref frame */ + sps->mode_delta[0] = 0; /* BPRED */ + sps->mode_delta[1] = 0; /* Zero */ + sps->mode_delta[2] = 0; /* New mv */ + sps->mode_delta[3] = 0; /* Split mv */ + return MPP_NOK; + } + + if (!ctx->picbuf.cur_pic->ipf && !ctx->picbuf.cur_pic->grf && + !ctx->picbuf.cur_pic->arf) { + memcpy(sps->ref_delta, sps->old_ref_delta, sizeof(sps->ref_delta)); + memcpy(sps->mode_delta, sps->old_mode_delta, sizeof(sps->mode_delta)); + return MPP_NOK; + } + + sps->ref_delta[0] = 2; /* Intra frame */ + sps->ref_delta[1] = 0; /* Last frame */ + sps->ref_delta[2] = -2; /* Golden frame */ + sps->ref_delta[3] = -2; /* Altref frame */ + + sps->mode_delta[0] = 4; /* BPRED */ + sps->mode_delta[1] = -2; /* Zero */ + sps->mode_delta[2] = 2; /* New mv */ + sps->mode_delta[3] = 4; /* Split mv */ + + { + RK_U32 i = 0; + for (i = 0; i < 4; i++) { + sps->ref_delta[i] = MPP_CLIP3(-0x3f, 0x3f, sps->ref_delta[i]); + sps->mode_delta[i] = MPP_CLIP3(-0x3f, 0x3f, sps->mode_delta[i]); + } + } + return MPP_OK; +} + +static MPP_RET set_segmentation(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8ePps *ppss = &ctx->ppss; + Pps *pps = ppss->pps; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + + { + RK_S32 qp = ctx->rc->qp_hdr; + + if (hw_cfg->roi1_delta_qp) + pps->qp_sgm[1] = MPP_CLIP3(0, 127, qp - hw_cfg->roi1_delta_qp); + + if (hw_cfg->roi2_delta_qp) + pps->qp_sgm[2] = MPP_CLIP3(0, 127, qp - hw_cfg->roi2_delta_qp); + } + + { + RK_U32 x, y, mb, mask, id; + RK_U32 *map = mpp_buffer_get_ptr(buffers->hw_segment_map_buf); + RK_U32 *map_bck = map; + RK_U32 mapSize = (ctx->mb_per_frame + 15) / 16 * 8; + + if (hw_cfg->roi1_delta_qp || hw_cfg->roi2_delta_qp) { + pps->segment_enabled = 1; + + memset(pps->sgm.id_cnt, 0, sizeof(pps->sgm.id_cnt)); + + for (y = 0, mb = 0, mask = 0; y < ctx->mb_per_col; y++) { + for (x = 0; x < ctx->mb_per_row; x++) { + id = 0; + if ((x >= hw_cfg->roi1_left) && (x <= hw_cfg->roi1_right) && + (y >= hw_cfg->roi1_top) && (y <= hw_cfg->roi1_bottom)) + id = 1; + if ((x >= hw_cfg->roi1_left) && (x <= hw_cfg->roi2_right) && + (y >= hw_cfg->roi2_top) && (y <= hw_cfg->roi2_bottom)) + id = 2; + + pps->sgm.id_cnt[id]++; + + mask |= id << (28 - 4 * (mb % 8)); + if ((mb % 8) == 7) { + *map++ = mask; + mask = 0; + } + mb++; + } + } + *map++ = mask; + vp8e_swap_endian(map_bck, mapSize); + } else if (pps->segment_enabled && pps->sgm.map_modified) { + memset(pps->sgm.id_cnt, 0, sizeof(pps->sgm.id_cnt)); + + for (mb = 0, mask = 0; mb < mapSize / 4; mb++) { + mask = map[mb]; + for (x = 0; x < 8; x++) { + if (mb * 8 + x < ctx->mb_per_frame) { + id = (mask >> (28 - 4 * x)) & 0xF; + pps->sgm.id_cnt[id]++; + } + } + } + vp8e_swap_endian(map_bck, mapSize); + } + } + if (ctx->picbuf.cur_pic->i_frame || !pps->segment_enabled) { + memset(ppss->qp_sgm, 0xff, sizeof(ppss->qp_sgm)); + memset(ppss->level_sgm, 0xff, sizeof(ppss->level_sgm)); + ppss->prev_pps = NULL; + } else + ppss->prev_pps = ppss->pps; + + return MPP_OK; +} + +static void set_intra_pred_penalties(Vp8eHwCfg *hw_cfg, RK_U32 qp) +{ + RK_S32 i, tmp; + + /* Intra 4x4 mode */ + tmp = qp * 2 + 8; + for (i = 0; i < 10; i++) { + hw_cfg->intra_b_mode_penalty[i] = (intra4_mode_tree_penalty_tbl[i] * tmp) >> 8; + } + + /* Intra 16x16 mode */ + tmp = qp * 2 + 64; + for (i = 0; i < 4; i++) { + hw_cfg->intra_mode_penalty[i] = (intra16_mode_tree_penalty_tbl[i] * tmp) >> 8; + } + + /* If favor has not been set earlier by testId use default */ + if (hw_cfg->intra_16_favor == -1) + hw_cfg->intra_16_favor = qp * 1024 / 128; +} + +static void set_hdr_segmentation(Vp8ePutBitBuf *bitbuf, Vp8ePps *ppss, + Vp8eHalEntropy *entropy) +{ + RK_S32 i, tmp; + RK_U8 data_modified = 0; + + Pps *pps = ppss->pps; + Sgm *sgm = &ppss->pps->sgm; + + if (memcmp(ppss->qp_sgm, pps->qp_sgm, sizeof(ppss->qp_sgm))) + data_modified = 1; + + if (memcmp(ppss->level_sgm, pps->level_sgm, sizeof(ppss->level_sgm))) + data_modified = 1; + + if (!ppss->prev_pps) { + sgm->map_modified = 1; + } + + vp8e_put_lit(bitbuf, sgm->map_modified, 1); + vp8e_put_lit(bitbuf, data_modified, 1); + + if (data_modified) { + vp8e_put_lit(bitbuf, 1, 1); + + for (i = 0; i < SGM_CNT; i++) { + tmp = pps->qp_sgm[i]; + vp8e_put_lit(bitbuf, 1, 1); + vp8e_put_lit(bitbuf, MPP_ABS(tmp), 7); + vp8e_put_lit(bitbuf, tmp < 0, 1); + } + + for (i = 0; i < SGM_CNT; i++) { + tmp = pps->level_sgm[i]; + vp8e_put_lit(bitbuf, 1, 1); + vp8e_put_lit(bitbuf, MPP_ABS(tmp), 6); + vp8e_put_lit(bitbuf, tmp < 0, 1); + } + } + + if (sgm->map_modified) { + RK_S32 sum1 = sgm->id_cnt[0] + sgm->id_cnt[1]; + RK_S32 sum2 = sgm->id_cnt[2] + sgm->id_cnt[3]; + + tmp = 255 * sum1 / (sum1 + sum2); + entropy->segment_prob[0] = MPP_CLIP3(1, 255, tmp); + + tmp = sum1 ? 255 * sgm->id_cnt[0] / sum1 : 255; + entropy->segment_prob[1] = MPP_CLIP3(1, 255, tmp); + + tmp = sum2 ? 255 * sgm->id_cnt[2] / sum2 : 255; + entropy->segment_prob[2] = MPP_CLIP3(1, 255, tmp); + + for (i = 0; i < 3; i++) { + if (sgm->id_cnt[i] != 0) { + vp8e_put_lit(bitbuf, 1, 1); + vp8e_put_lit(bitbuf, entropy->segment_prob[i], 8); + } else { + vp8e_put_lit(bitbuf, 0, 1); + } + } + } + + memcpy(ppss->qp_sgm, pps->qp_sgm, sizeof(ppss->qp_sgm)); + memcpy(ppss->level_sgm, pps->level_sgm, sizeof(ppss->level_sgm)); +} + +static void set_filter_level_delta(Vp8ePutBitBuf *bitbuf, Vp8eSps *sps) +{ + RK_S32 i, tmp; + RK_U8 update = 0; + RK_S32 mode_update[4]; + RK_S32 ref_update[4]; + + for (i = 0; i < 4; i++) { + mode_update[i] = sps->mode_delta[i] != sps->old_mode_delta[i]; + ref_update[i] = sps->ref_delta[i] != sps->old_ref_delta[i]; + if (mode_update[i] || ref_update[i]) + update = 1; + } + + if (!sps->refresh_entropy) + update = 1; + + vp8e_put_lit(bitbuf, update, 1); + if (!update) + return; + + for (i = 0; i < 4; i++) { + vp8e_put_lit(bitbuf, ref_update[i], 1); + if (ref_update[i]) { + tmp = sps->ref_delta[i]; + vp8e_put_lit(bitbuf, MPP_ABS(tmp), 6); + vp8e_put_lit(bitbuf, tmp < 0, 1); + } + } + + for (i = 0; i < 4; i++) { + vp8e_put_lit(bitbuf, mode_update[i], 1); + if (mode_update[i]) { + tmp = sps->mode_delta[i]; + vp8e_put_lit(bitbuf, MPP_ABS(tmp), 6); + vp8e_put_lit(bitbuf, tmp < 0, 1); + } + } + + memcpy(sps->old_ref_delta, sps->ref_delta, sizeof(sps->ref_delta)); + memcpy(sps->old_mode_delta, sps->mode_delta, sizeof(sps->mode_delta)); +} + +static MPP_RET set_frame_header(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eSps *sps = &ctx->sps; + Pps *pps = ctx->ppss.pps; + + Vp8ePutBitBuf *bitbuf = &ctx->bitbuf[1]; + HalVp8eRefPic *cur_pic = ctx->picbuf.cur_pic; + Vp8eHalEntropy *entropy = &ctx->entropy; + + if (cur_pic->i_frame) { + vp8e_put_lit(bitbuf, sps->color_type, 1); + + vp8e_put_lit(bitbuf, sps->clamp_type, 1); + } + + vp8e_put_lit(bitbuf, pps->segment_enabled, 1); + if (pps->segment_enabled) + set_hdr_segmentation(bitbuf, &ctx->ppss, entropy); + + vp8e_put_lit(bitbuf, sps->filter_type, 1); + + vp8e_put_lit(bitbuf, sps->filter_level, 6); + + vp8e_put_lit(bitbuf, sps->filter_sharpness, 3); + + vp8e_put_lit(bitbuf, sps->filter_delta_enable, 1); + if (sps->filter_delta_enable) { + /* Filter level delta references reset by key frame */ + if (cur_pic->i_frame) { + memset(sps->old_ref_delta, 0, sizeof(sps->ref_delta)); + memset(sps->old_mode_delta, 0, sizeof(sps->mode_delta)); + } + set_filter_level_delta(bitbuf, sps); + } + + vp8e_put_lit(bitbuf, sps->dct_partitions, 2); + + vp8e_put_lit(bitbuf, ctx->rc->qp_hdr, 7); + + vp8e_put_lit(bitbuf, 0, 1); + vp8e_put_lit(bitbuf, 0, 1); + vp8e_put_lit(bitbuf, 0, 1); + vp8e_put_lit(bitbuf, 0, 1); + vp8e_put_lit(bitbuf, 0, 1); + + if (!cur_pic->i_frame) { + HalVp8eRefPic *ref_pic_list = ctx->picbuf.ref_pic_list; + + vp8e_put_lit(bitbuf, cur_pic->grf, 1); /* Grf refresh */ + vp8e_put_lit(bitbuf, cur_pic->arf, 1); /* Arf refresh */ + + if (!cur_pic->grf) { + if (ref_pic_list[0].grf) { + vp8e_put_lit(bitbuf, 1, 2); /* Ipf -> grf */ + } else if (ref_pic_list[2].grf) { + vp8e_put_lit(bitbuf, 2, 2); /* Arf -> grf */ + } else { + vp8e_put_lit(bitbuf, 0, 2); /* Not updated */ + } + } + + if (!cur_pic->arf) { + if (ref_pic_list[0].arf) { + vp8e_put_lit(bitbuf, 1, 2); /* Ipf -> arf */ + } else if (ref_pic_list[1].arf) { + vp8e_put_lit(bitbuf, 2, 2); /* Grf -> arf */ + } else { + vp8e_put_lit(bitbuf, 0, 2); /* Not updated */ + } + } + + vp8e_put_lit(bitbuf, sps->sing_bias[1], 1); /* Grf */ + vp8e_put_lit(bitbuf, sps->sing_bias[2], 1); /* Arf */ + } + + vp8e_put_lit(bitbuf, sps->refresh_entropy, 1); + if (!cur_pic->i_frame) { + vp8e_put_lit(bitbuf, cur_pic->ipf, 1); + } + vp8e_calc_coeff_prob(bitbuf, &entropy->coeff_prob, &entropy->old_coeff_prob); + vp8e_put_lit(bitbuf, 1, 1); + vp8e_put_lit(bitbuf, entropy->skip_false_prob, 8); + + if (cur_pic->i_frame) + return MPP_OK; + + vp8e_put_lit(bitbuf, entropy->intra_prob, 8); + vp8e_put_lit(bitbuf, entropy->last_prob, 8); + vp8e_put_lit(bitbuf, entropy->gf_prob, 8); + vp8e_put_lit(bitbuf, 0, 1); + vp8e_put_lit(bitbuf, 0, 1); + vp8e_calc_mv_prob(bitbuf, &entropy->mv_prob, &entropy->old_mv_prob); + + return MPP_OK; +} + +static MPP_RET set_new_frame(void *hal) +{ + RK_S32 i; + RK_S32 qp; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eSps *sps = &ctx->sps; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + + hw_cfg->output_strm_size /= 8; + hw_cfg->output_strm_size &= (~0x07); + + { + RK_S32 offset = hw_cfg->output_strm_base >> 10; + RK_S32 fd = hw_cfg->output_strm_base & 0x3ff; + + offset += ctx->bitbuf[1].byte_cnt; + hw_cfg->output_strm_base = fd | ((offset & (~7)) << 10); + hw_cfg->first_free_bit = (offset & 0x07) * 8; + } + + if (hw_cfg->first_free_bit != 0) { + RK_U32 val; + RK_U8 *pTmp = (RK_U8 *)((size_t)(ctx->bitbuf[1].data) & (RK_U32)(~0x07)); + + for (val = 6; val >= hw_cfg->first_free_bit / 8; val--) { + pTmp[val] = 0; + } + + val = pTmp[0] << 24; + val |= pTmp[1] << 16; + val |= pTmp[2] << 8; + val |= pTmp[3]; + + hw_cfg->strm_start_msb = val; + + if (hw_cfg->first_free_bit > 32) { + val = pTmp[4] << 24; + val |= pTmp[5] << 16; + val |= pTmp[6] << 8; + + hw_cfg->strm_start_lsb = val; + } else { + hw_cfg->strm_start_lsb = 0; + } + } else { + hw_cfg->strm_start_msb = hw_cfg->strm_start_lsb = 0; + } + + if (sps->quarter_pixel_mv == 0) { + hw_cfg->disable_qp_mv = 1; + } else if (sps->quarter_pixel_mv == 1) { + if (ctx->mb_per_frame > 8160) + hw_cfg->disable_qp_mv = 1; + else + hw_cfg->disable_qp_mv = 0; + } else { + hw_cfg->disable_qp_mv = 0; + } + + hw_cfg->enable_cabac = 1; + + if (sps->split_mv == 0) + hw_cfg->split_mv_mode = 0; + else if (sps->split_mv == 1) { + if (ctx->mb_per_frame > 1584) + hw_cfg->split_mv_mode = 0; + else + hw_cfg->split_mv_mode = 1; + } else + hw_cfg->split_mv_mode = 1; + + qp = ctx->rc->qp_hdr; + if (hw_cfg->inter_favor == -1) { + RK_S32 tmp = 128 - ctx->entropy.intra_prob; + + if (tmp < 0) { + hw_cfg->inter_favor = tmp & 0xFFFF; + } else { + tmp = qp * 2 - 40; + hw_cfg->inter_favor = MPP_MAX(0, tmp); + } + } + + if (hw_cfg->diff_mv_penalty[0] == -1) + hw_cfg->diff_mv_penalty[0] = 64 / 2; + if (hw_cfg->diff_mv_penalty[1] == -1) + hw_cfg->diff_mv_penalty[1] = 60 / 2 * 32; + if (hw_cfg->diff_mv_penalty[2] == -1) + hw_cfg->diff_mv_penalty[2] = 8; + if (hw_cfg->skip_penalty == -1) + hw_cfg->skip_penalty = (qp >= 100) ? (3 * qp / 4) : 0; /* Zero/nearest/near */ + if (hw_cfg->golden_penalty == -1) + hw_cfg->golden_penalty = MPP_MAX(0, 5 * qp / 4 - 10); + if (hw_cfg->split_penalty[0] == 0) + hw_cfg->split_penalty[0] = MPP_MIN(1023, vp8_split_penalty_tbl[qp] / 2); + if (hw_cfg->split_penalty[1] == 0) + hw_cfg->split_penalty[1] = MPP_MIN(1023, (2 * vp8_split_penalty_tbl[qp] + 40) / 4); + if (hw_cfg->split_penalty[3] == 0) + hw_cfg->split_penalty[3] = MPP_MIN(511, (8 * vp8_split_penalty_tbl[qp] + 500) / 16); + + for (i = 0; i < 128; i++) { + RK_S32 y, x; + + hw_cfg->dmv_penalty[i] = i * 2; + y = vp8e_calc_cost_mv(i * 2, ctx->entropy.mv_prob[0]); /* mv y */ + x = vp8e_calc_cost_mv(i * 2, ctx->entropy.mv_prob[1]); /* mv x */ + hw_cfg->dmv_qpel_penalty[i] = MPP_MIN(255, (y + x + 1) / 2 * weight_tbl[qp] >> 8); + } + + for (i = 0; i < 4; i++) { + qp = ctx->ppss.pps->qp_sgm[i]; + hw_cfg->y1_quant_dc[i] = ctx->qp_y1[qp].quant[0]; + hw_cfg->y1_quant_ac[i] = ctx->qp_y1[qp].quant[1]; + hw_cfg->y2_quant_dc[i] = ctx->qp_y2[qp].quant[0]; + hw_cfg->y2_quant_ac[i] = ctx->qp_y2[qp].quant[1]; + hw_cfg->ch_quant_dc[i] = ctx->qp_ch[qp].quant[0]; + hw_cfg->ch_quant_ac[i] = ctx->qp_ch[qp].quant[1]; + hw_cfg->y1_zbin_dc[i] = ctx->qp_y1[qp].zbin[0]; + hw_cfg->y1_zbin_ac[i] = ctx->qp_y1[qp].zbin[1]; + hw_cfg->y2_zbin_dc[i] = ctx->qp_y2[qp].zbin[0]; + hw_cfg->y2_zbin_ac[i] = ctx->qp_y2[qp].zbin[1]; + hw_cfg->ch_zbin_dc[i] = ctx->qp_ch[qp].zbin[0]; + hw_cfg->ch_zbin_ac[i] = ctx->qp_ch[qp].zbin[1]; + hw_cfg->y1_round_dc[i] = ctx->qp_y1[qp].round[0]; + hw_cfg->y1_round_ac[i] = ctx->qp_y1[qp].round[1]; + hw_cfg->y2_round_dc[i] = ctx->qp_y2[qp].round[0]; + hw_cfg->y2_round_ac[i] = ctx->qp_y2[qp].round[1]; + hw_cfg->ch_round_dc[i] = ctx->qp_ch[qp].round[0]; + hw_cfg->ch_round_ac[i] = ctx->qp_ch[qp].round[1]; + hw_cfg->y1_dequant_dc[i] = ctx->qp_y1[qp].dequant[0]; + hw_cfg->y1_dequant_ac[i] = ctx->qp_y1[qp].dequant[1]; + hw_cfg->y2_dequant_dc[i] = ctx->qp_y2[qp].dequant[0]; + hw_cfg->y2_dequant_ac[i] = ctx->qp_y2[qp].dequant[1]; + hw_cfg->ch_dequant_dc[i] = ctx->qp_ch[qp].dequant[0]; + hw_cfg->ch_dequant_ac[i] = ctx->qp_ch[qp].dequant[1]; + + hw_cfg->filter_level[i] = ctx->ppss.pps->level_sgm[i]; + } + + hw_cfg->bool_enc_value = ctx->bitbuf[1].bottom; + hw_cfg->bool_enc_value_bits = 24 - ctx->bitbuf[1].bits_left; + hw_cfg->bool_enc_range = ctx->bitbuf[1].range; + + if (ctx->picbuf.cur_pic->i_frame) + hw_cfg->frame_coding_type = 1; + else + hw_cfg->frame_coding_type = 0; + + hw_cfg->size_tbl_base = mpp_buffer_get_fd(buffers->hw_size_table_buf); + + hw_cfg->dct_partitions = sps->dct_partitions; + hw_cfg->filter_disable = sps->filter_type; + hw_cfg->filter_sharpness = sps->filter_sharpness; + hw_cfg->segment_enable = ctx->ppss.pps->segment_enabled; + hw_cfg->segment_map_update = ctx->ppss.pps->sgm.map_modified; + + ctx->ppss.pps->sgm.map_modified = 0; + + for (i = 0; i < 4; i++) { + hw_cfg->lf_ref_delta[i] = sps->ref_delta[i]; + hw_cfg->lf_mode_delta[i] = sps->mode_delta[i]; + } + + set_intra_pred_penalties(hw_cfg, qp); + + memset(mpp_buffer_get_ptr(buffers->hw_prob_count_buf), + 0, VP8_PROB_COUNT_BUF_SIZE); + + return MPP_OK; +} + +static MPP_RET set_code_frame(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *) hal; + + vp8e_init_entropy(ctx); + set_segmentation(ctx); + set_filter(ctx); + set_frame_header(ctx); + set_new_frame(ctx); + vp8e_write_entropy_tables(ctx); + + return MPP_OK; +} + +static void reset_refpic(HalVp8eRefPic *refPic) +{ + refPic->poc = -1; + refPic->i_frame = 0; + refPic->p_frame = 0; + refPic->show = 0; + refPic->ipf = 0; + refPic->arf = 0; + refPic->grf = 0; + refPic->search = 0; +} + +static void init_ref_pic_list(HalVp8ePicBuf *picbuf) +{ + RK_S32 i, j; + + HalVp8eRefPic *ref_pic = picbuf->ref_pic; + HalVp8eRefPic *cur_pic = picbuf->cur_pic; + HalVp8eRefPic *ref_pic_list = picbuf->ref_pic_list; + + j = 0; + for (i = 0; i < picbuf->size + 1; i++) { + if (ref_pic[i].ipf && (&ref_pic[i] != cur_pic)) { + ref_pic_list[j++] = ref_pic[i]; + break; + } + } + + for (i = 0; i < picbuf->size + 1; i++) { + if (ref_pic[i].grf && (&ref_pic[i] != cur_pic)) { + ref_pic_list[j++] = ref_pic[i]; + break; + } + } + + for (i = 0; i < picbuf->size + 1; i++) { + if (ref_pic[i].arf && (&ref_pic[i] != cur_pic)) { + ref_pic_list[j] = ref_pic[i]; + break; + } + } + + for (i = 0; i < picbuf->size; i++) { + ref_pic_list[i].ipf = 0; + ref_pic_list[i].grf = 0; + ref_pic_list[i].arf = 0; + } +} + +static MPP_RET init_picbuf(void *hal) +{ + RK_S32 i = 0; + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + HalVp8ePicBuf *buf = &ctx->picbuf; + + if (buf->cur_pic->i_frame) { + buf->cur_pic->p_frame = 0; + buf->cur_pic->ipf = 1; + buf->cur_pic->grf = 1; + buf->cur_pic->arf = 1; + + for (i = 0; i < 4; i++) { + if (&buf->ref_pic[i] != buf->cur_pic) { + reset_refpic(&buf->ref_pic[i]); + } + } + } + + for (i = 0; i < 3; i++) { + reset_refpic(&buf->ref_pic_list[i]); + } + + init_ref_pic_list(buf); + + return MPP_OK; +} + +static MPP_RET set_picbuf_ref(void *hal) +{ + RK_S32 i = 0; + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + HalVp8ePicBuf *pic_buf = &ctx->picbuf; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + HalVp8eRefPic *ref_pic_list = pic_buf->ref_pic_list; + + { + RK_S32 no_grf = 0; + RK_S32 no_arf = 0; + if (pic_buf->size < 2) { + no_grf = 1; + pic_buf->cur_pic->grf = 0; + } + if (pic_buf->size < 3) { + no_arf = 1; + pic_buf->cur_pic->arf = 0; + } + + for (i = 0; i < pic_buf->size; i++) { + if (pic_buf->cur_pic->grf || no_grf) + pic_buf->ref_pic_list[i].grf = 0; + if (pic_buf->cur_pic->arf || no_arf) + pic_buf->ref_pic_list[i].arf = 0; + } + } + { + RK_S32 ref_idx = -1; + RK_S32 ref_idx2 = -1; + + for (i = 0; i < 3; i++) { + if ((i < pic_buf->size) && ref_pic_list[i].search) { + if (ref_idx == -1) + ref_idx = i; + else if (ref_idx2 == -1) + ref_idx2 = i; + else + ref_pic_list[i].search = 0; + } else { + ref_pic_list[i].search = 0; + } + } + + if (ref_idx == -1) + ref_idx = 0; + + hw_cfg->mv_ref_idx[0] = hw_cfg->mv_ref_idx[1] = ref_idx; + + if (pic_buf->cur_pic->p_frame) { + pic_buf->ref_pic_list[ref_idx].search = 1; + + hw_cfg->internal_img_lum_base_r[0] = ref_pic_list[ref_idx].picture.lum; + hw_cfg->internal_img_chr_base_r[0] = ref_pic_list[ref_idx].picture.cb; + hw_cfg->internal_img_lum_base_r[1] = ref_pic_list[ref_idx].picture.lum; + hw_cfg->internal_img_chr_base_r[1] = ref_pic_list[ref_idx].picture.cb; + hw_cfg->mv_ref_idx[0] = hw_cfg->mv_ref_idx[1] = ref_idx; + hw_cfg->ref2_enable = 0; + + if (ref_idx2 != -1) { + hw_cfg->internal_img_lum_base_r[1] = ref_pic_list[ref_idx2].picture.lum; + hw_cfg->internal_img_chr_base_r[1] = ref_pic_list[ref_idx2].picture.cb; + hw_cfg->mv_ref_idx[1] = ref_idx2; + hw_cfg->ref2_enable = 1; + } + } + } + hw_cfg->rec_write_disable = 0; + + if (!pic_buf->cur_pic->picture.lum) { + HalVp8eRefPic *cur_pic = pic_buf->cur_pic; + HalVp8eRefPic *cand; + RK_S32 recIdx = -1; + + for (i = 0; i < pic_buf->size + 1; i++) { + cand = &pic_buf->ref_pic[i]; + if (cand == cur_pic) + continue; + if (((cur_pic->ipf | cand->ipf) == cur_pic->ipf) && + ((cur_pic->grf | cand->grf) == cur_pic->grf) && + ((cur_pic->arf | cand->arf) == cur_pic->arf)) + recIdx = i; + } + + if (recIdx >= 0) { + cur_pic->picture.lum = pic_buf->ref_pic[recIdx].picture.lum; + pic_buf->ref_pic[recIdx].picture.lum = 0; + } else { + hw_cfg->rec_write_disable = 1; + } + } + + hw_cfg->internal_img_lum_base_w = pic_buf->cur_pic->picture.lum; + hw_cfg->internal_img_chr_base_w = pic_buf->cur_pic->picture.cb; + + return MPP_OK; +} + +static void write_ivf_header(void *hal, RK_U8 *out) +{ + RK_U8 data[IVF_HDR_BYTES] = {0}; + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + MppEncPrepCfg *prep = &ctx->cfg->prep; + MppEncRcCfg *rc = &ctx->cfg->rc; + + data[0] = 'D'; + data[1] = 'K'; + data[2] = 'I'; + data[3] = 'F'; + + data[6] = 32; + + data[8] = 'V'; + data[9] = 'P'; + data[10] = '8'; + data[11] = '0'; + + data[12] = prep->width & 0xff; + data[13] = (prep->width >> 8) & 0xff; + data[14] = prep->height & 0xff; + data[15] = (prep->height >> 8) & 0xff; + + data[16] = rc->fps_out_num & 0xff; + data[17] = (rc->fps_out_num >> 8) & 0xff; + data[18] = (rc->fps_out_num >> 16) & 0xff; + data[19] = (rc->fps_out_num >> 24) & 0xff; + + data[20] = rc->fps_out_denorm & 0xff; + data[21] = (rc->fps_out_denorm >> 8) & 0xff; + data[22] = (rc->fps_out_denorm >> 16) & 0xff; + data[23] = (rc->fps_out_denorm >> 24) & 0xff; + + data[24] = ctx->frame_cnt & 0xff; + data[25] = (ctx->frame_cnt >> 8) & 0xff; + data[26] = (ctx->frame_cnt >> 16) & 0xff; + data[27] = (ctx->frame_cnt >> 24) & 0xff; + + memcpy(out, data, IVF_HDR_BYTES); +} + +static void write_ivf_frame(void *hal, RK_U8 *out) +{ + RK_U8 data[IVF_FRM_BYTES]; + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + RK_S32 byte_cnt = ctx->frame_size; + + data[0] = byte_cnt & 0xff; + data[1] = (byte_cnt >> 8) & 0xff; + data[2] = (byte_cnt >> 16) & 0xff; + data[3] = (byte_cnt >> 24) & 0xff; + + data[4] = ctx->frame_cnt & 0xff; + data[5] = (ctx->frame_cnt >> 8) & 0xff; + data[6] = (ctx->frame_cnt >> 16) & 0xff; + data[7] = (ctx->frame_cnt >> 24) & 0xff; + data[8] = (ctx->frame_cnt >> 32) & 0xff; + data[9] = (ctx->frame_cnt >> 40) & 0xff; + data[10] = (ctx->frame_cnt >> 48) & 0xff; + data[11] = (ctx->frame_cnt >> 56) & 0xff; + + memcpy(out, data, IVF_FRM_BYTES); +} + +static MPP_RET set_frame_tag(void *hal) +{ + RK_S32 tmp = 0; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + HalVp8ePicBuf *pic_buf = &ctx->picbuf; + HalVp8eRefPic *cur_pic = pic_buf->cur_pic; + Vp8ePutBitBuf *bitbuf = &ctx->bitbuf[0]; + + tmp = ((ctx->bitbuf[1].byte_cnt) << 5) | + ((cur_pic->show ? 1 : 0) << 4) | + (ctx->sps.profile << 1) | + (cur_pic->i_frame ? 0 : 1); + + vp8e_put_byte(bitbuf, tmp & 0xff); + + vp8e_put_byte(bitbuf, (tmp >> 8) & 0xff); + + vp8e_put_byte(bitbuf, (tmp >> 16) & 0xff); + + if (!cur_pic->i_frame) + return MPP_NOK; + + vp8e_put_byte(bitbuf, 0x9d); + vp8e_put_byte(bitbuf, 0x01); + vp8e_put_byte(bitbuf, 0x2a); + + tmp = ctx->sps.pic_width_in_pixel | (ctx->sps.horizontal_scaling << 14); + vp8e_put_byte(bitbuf, tmp & 0xff); + vp8e_put_byte(bitbuf, tmp >> 8); + + tmp = ctx->sps.pic_height_in_pixel | (ctx->sps.vertical_scaling << 14); + vp8e_put_byte(bitbuf, tmp & 0xff); + vp8e_put_byte(bitbuf, tmp >> 8); + + return MPP_OK; +} + +static MPP_RET set_data_part_size(void *hal) +{ + RK_S32 i = 0; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + if (!ctx->sps.dct_partitions) + return MPP_NOK; + + for (i = 2; i < ctx->sps.partition_cnt - 1; i++) { + Vp8ePutBitBuf *bitbuf = ctx->bitbuf; + RK_S32 tmp = bitbuf[i].data - bitbuf[i].p_data; + vp8e_put_byte(&bitbuf[1], tmp & 0xff); + vp8e_put_byte(&bitbuf[1], (tmp >> 8) & 0xff); + vp8e_put_byte(&bitbuf[1], (tmp >> 16) & 0xff); + } + + return MPP_OK; +} + +static MPP_RET update_picbuf(HalVp8ePicBuf *picbuf) +{ + RK_S32 i , j; + + HalVp8eRefPic *ref_pic_list = picbuf->ref_pic_list; + HalVp8eRefPic *ref_pic = picbuf->ref_pic; + HalVp8eRefPic *cur_pic = picbuf->cur_pic; + + picbuf->last_pic = picbuf->cur_pic; + + for (i = 0; i < picbuf->size + 1; i++) { + if (&ref_pic[i] == cur_pic) + continue; + if (cur_pic->ipf) + ref_pic[i].ipf = 0; + if (cur_pic->grf) + ref_pic[i].grf = 0; + if (cur_pic->arf) + ref_pic[i].arf = 0; + } + + for (i = 0; i < picbuf->size; i++) { + for (j = 0; j < picbuf->size + 1; j++) { + if (ref_pic_list[i].grf) + ref_pic[j].grf = 0; + if (ref_pic_list[i].arf) + ref_pic[j].arf = 0; + } + } + + for (i = 0; i < picbuf->size; i++) { + if (ref_pic_list[i].grf) + ref_pic_list[i].refPic->grf = 1; + if (ref_pic_list[i].arf) + ref_pic_list[i].refPic->arf = 1; + } + + for (i = 0; i < picbuf->size + 1; i++) { + HalVp8eRefPic *tmp = &ref_pic[i]; + if (!tmp->ipf && !tmp->arf && !tmp->grf) { + picbuf->cur_pic = &ref_pic[i]; + break; + } + } + + return MPP_OK; +} + +static MPP_RET set_parameter(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eSps *sps = &ctx->sps; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + MppEncPrepCfg *set = &ctx->cfg->prep; + + RK_S32 width = 16 * ((set->width + 15) / 16); + RK_S32 height = 16 * ((set->height + 15) / 16); + RK_U32 stride = MPP_ALIGN(width, 16); + + //TODO handle rotation + + ctx->mb_per_frame = width / 16 * height / 16; + ctx->mb_per_row = width / 16; + ctx->mb_per_col = width / 16; + + ctx->gop_len = ctx->cfg->rc.gop; + ctx->bit_rate = ctx->cfg->rc.bps_target; + + sps->pic_width_in_pixel = width; + sps->pic_height_in_pixel = height; + sps->pic_width_in_mbs = width / 16; + sps->pic_height_in_mbs = height / 16; + sps->horizontal_scaling = 0; + sps->vertical_scaling = 0; + sps->color_type = 0; + sps->clamp_type = 0; + sps->dct_partitions = 0; + sps->partition_cnt = 2 + (1 << sps->dct_partitions); + sps->profile = 1; + sps->filter_type = 0; + sps->filter_level = 0; + sps->filter_sharpness = 0; + sps->auto_filter_level = 1; + sps->auto_filter_sharpness = 1; + sps->quarter_pixel_mv = 1; + sps->split_mv = 1; + sps->refresh_entropy = 1; + memset(sps->sing_bias, 0, sizeof(sps->sing_bias)); + + sps->filter_delta_enable = 1; + memset(sps->ref_delta, 0, sizeof(sps->ref_delta)); + memset(sps->mode_delta, 0, sizeof(sps->mode_delta)); + + hw_cfg->input_rotation = set->rotation; + + { + RK_U32 tmp = 0; + RK_U32 hor_offset_src = 0; + RK_U32 ver_offset_src = 0; + RK_U8 video_stab = 0; + + if (set->format == MPP_FMT_YUV420SP || set->format == MPP_FMT_YUV420P) { + tmp = ver_offset_src; + tmp *= stride; + tmp += hor_offset_src; + hw_cfg->input_lum_base += (tmp & (~7)); + hw_cfg->input_luma_base_offset = tmp & 7; + + if (video_stab) + hw_cfg->vs_next_luma_base += (tmp & (~7)); + + if (set->format == MPP_FMT_YUV420P) { + tmp = ver_offset_src / 2; + tmp *= stride / 2; + tmp += hor_offset_src / 2; + + hw_cfg->input_cb_base += (tmp & (~7)); + hw_cfg->input_cr_base += (tmp & (~7)); + hw_cfg->input_chroma_base_offset = tmp & 7; + } else { + tmp = ver_offset_src / 2; + tmp *= stride / 2; + tmp += hor_offset_src / 2; + tmp *= 2; + + hw_cfg->input_cb_base += (tmp & (~7)); + hw_cfg->input_chroma_base_offset = tmp & 7; + } + } else if (set->format <= MPP_FMT_BGR444 && set->format >= MPP_FMT_RGB565) { + tmp = ver_offset_src; + tmp *= stride; + tmp += hor_offset_src; + tmp *= 2; + + hw_cfg->input_lum_base += (tmp & (~7)); + hw_cfg->input_luma_base_offset = tmp & 7; + hw_cfg->input_chroma_base_offset = (hw_cfg->input_luma_base_offset / 4) * 4; + + if (video_stab) + hw_cfg->vs_next_luma_base += (tmp & (~7)); + } else { + tmp = ver_offset_src; + tmp *= stride; + tmp += hor_offset_src; + tmp *= 4; + + hw_cfg->input_lum_base += (tmp & (~7)); + hw_cfg->input_luma_base_offset = (tmp & 7) / 2; + + if (video_stab) + hw_cfg->vs_next_luma_base += (tmp & (~7)); + } + + hw_cfg->mbs_in_row = (set->width + 15) / 16; + hw_cfg->mbs_in_col = (set->height + 15) / 16; + hw_cfg->pixels_on_row = stride; + } + if (set->width & 0x0F) + hw_cfg->x_fill = (16 - (set->width & 0x0F)) / 4; + else + hw_cfg->x_fill = 0; + + if (set->height & 0x0F) + hw_cfg->y_fill = 16 - (set->height & 0x0F); + else + hw_cfg->y_fill = 0; + + hw_cfg->vs_mode = 0; + + switch (set->color) { + case MPP_FRAME_SPC_RGB: /* BT.601 */ + default: + /* Y = 0.2989 R + 0.5866 G + 0.1145 B + * Cb = 0.5647 (B - Y) + 128 + * Cr = 0.7132 (R - Y) + 128 + */ + hw_cfg->rgb_coeff_a = 19589; + hw_cfg->rgb_coeff_b = 38443; + hw_cfg->rgb_coeff_c = 7504; + hw_cfg->rgb_coeff_e = 37008; + hw_cfg->rgb_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 + */ + hw_cfg->rgb_coeff_a = 13933; + hw_cfg->rgb_coeff_b = 46871; + hw_cfg->rgb_coeff_c = 732; + hw_cfg->rgb_coeff_e = 35317; + hw_cfg->rgb_coeff_f = 41615; + break; + } + + hw_cfg->r_mask_msb = hw_cfg->g_mask_msb = hw_cfg->b_mask_msb = 0; + switch (set->format) { + case MPP_FMT_YUV420P: + hw_cfg->input_format = INPUT_YUV420PLANAR; + break; + case MPP_FMT_YUV420SP: + hw_cfg->input_format = INPUT_YUV420SEMIPLANAR; + break; + case MPP_FMT_YUV422_YUYV: + hw_cfg->input_format = INPUT_YUYV422INTERLEAVED; + break; + case MPP_FMT_YUV422_UYVY: + hw_cfg->input_format = INPUT_UYVY422INTERLEAVED; + break; + case MPP_FMT_RGB565: + hw_cfg->input_format = INPUT_RGB565; + hw_cfg->r_mask_msb = 15; + hw_cfg->g_mask_msb = 10; + hw_cfg->b_mask_msb = 4; + break; + case MPP_FMT_BGR565: + hw_cfg->input_format = INPUT_RGB565; + hw_cfg->b_mask_msb = 15; + hw_cfg->g_mask_msb = 10; + hw_cfg->r_mask_msb = 4; + break; + case MPP_FMT_RGB555: + hw_cfg->input_format = INPUT_RGB555; + hw_cfg->r_mask_msb = 14; + hw_cfg->g_mask_msb = 9; + hw_cfg->b_mask_msb = 4; + break; + case MPP_FMT_BGR555: + hw_cfg->input_format = INPUT_RGB555; + hw_cfg->b_mask_msb = 14; + hw_cfg->g_mask_msb = 9; + hw_cfg->r_mask_msb = 4; + break; + case MPP_FMT_RGB444: + hw_cfg->input_format = INPUT_RGB444; + hw_cfg->r_mask_msb = 11; + hw_cfg->g_mask_msb = 7; + hw_cfg->b_mask_msb = 3; + break; + case MPP_FMT_BGR444: + hw_cfg->input_format = INPUT_RGB444; + hw_cfg->b_mask_msb = 11; + hw_cfg->g_mask_msb = 7; + hw_cfg->r_mask_msb = 3; + break; + case MPP_FMT_RGB888: + hw_cfg->input_format = INPUT_RGB888; + hw_cfg->r_mask_msb = 23; + hw_cfg->g_mask_msb = 15; + hw_cfg->b_mask_msb = 7; + break; + case MPP_FMT_BGR888: + hw_cfg->input_format = INPUT_RGB888; + hw_cfg->b_mask_msb = 23; + hw_cfg->g_mask_msb = 15; + hw_cfg->r_mask_msb = 7; + break; + case MPP_FMT_RGB101010: + hw_cfg->input_format = INPUT_RGB101010; + hw_cfg->r_mask_msb = 29; + hw_cfg->g_mask_msb = 19; + hw_cfg->b_mask_msb = 9; + break; + case MPP_FMT_BGR101010: + hw_cfg->input_format = INPUT_RGB101010; + hw_cfg->b_mask_msb = 29; + hw_cfg->g_mask_msb = 19; + hw_cfg->r_mask_msb = 9; + break; + default: + mpp_err("unsupported color format %d", set->format); + return MPP_NOK; + break; + } + + return MPP_OK; +} + +static MPP_RET set_picbuf(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + // find one dpb for current picture + { + RK_U32 i = 0; + RK_S32 width = ctx->sps.pic_width_in_mbs * 16; + RK_S32 height = ctx->sps.pic_height_in_mbs * 16; + HalVp8ePicBuf *picbuf = &ctx->picbuf; + + memset(picbuf->ref_pic, 0, sizeof(picbuf->ref_pic)); + memset(picbuf->ref_pic_list, 0, sizeof(picbuf->ref_pic_list)); + + for (i = 0; i < REF_FRAME_COUNT + 1; i++) { + picbuf->ref_pic[i].picture.lum_width = width; + picbuf->ref_pic[i].picture.lum_height = height; + picbuf->ref_pic[i].picture.ch_width = width / 2; + picbuf->ref_pic[i].picture.ch_height = height / 2; + picbuf->ref_pic[i].picture.lum = 0; + picbuf->ref_pic[i].picture.cb = 0; + } + + picbuf->cur_pic = &picbuf->ref_pic[0]; + } + + ctx->ppss.size = 1; + ctx->ppss.store = (Pps *)mpp_calloc(Pps, 1); + if (ctx->ppss.store == NULL) { + mpp_err("failed to malloc ppss store.\n"); + goto __ERR_RET; + } + + ctx->ppss.pps = ctx->ppss.store; + ctx->ppss.pps->segment_enabled = 0; + ctx->ppss.pps->sgm.map_modified = 0; + + return MPP_OK; + +__ERR_RET: + return MPP_NOK; +} + +static MPP_RET alloc_buffer(void *hal) +{ + MPP_RET ret = MPP_OK; + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + MppEncPrepCfg *pre = &ctx->cfg->prep; + RK_U32 mb_total = ctx->mb_per_frame; + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + + //set coding format as VP8 + hw_cfg->coding_type = 1; + + ret = mpp_buffer_group_get_internal(&buffers->hw_buf_grp, + MPP_BUFFER_TYPE_ION); + if (ret) { + mpp_err("buf group get failed ret %d\n", ret); + goto __ERR_RET; + } + + //add 128 bytes to avoid kernel crash + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_luma_buf, + mb_total * (16 * 16) + 128); + if (ret) { + mpp_err("hw_luma_buf get failed ret %d\n", ret); + goto __ERR_RET; + } + { + RK_U32 i = 0; + for (i = 0; i < 2; i++) { + //add 128 bytes to avoid kernel crash + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_cbcr_buf[i], + mb_total * (2 * 8 * 8) + 128); + if (ret) { + mpp_err("hw_cbcr_buf[%d] get failed ret %d\n", i, ret); + goto __ERR_RET; + } + } + } + hw_cfg->internal_img_lum_base_w = mpp_buffer_get_fd(buffers->hw_luma_buf); + hw_cfg->internal_img_chr_base_w = mpp_buffer_get_fd(buffers->hw_cbcr_buf[0]); + + hw_cfg->internal_img_lum_base_r[0] = mpp_buffer_get_fd(buffers->hw_luma_buf); + hw_cfg->internal_img_chr_base_r[0] = mpp_buffer_get_fd(buffers->hw_cbcr_buf[1]); + { + /* NAL size table, table size must be 64-bit multiple, + * space for SEI, MVC prefix, filler and zero at the end of table. + * At least 1 macroblock row in every slice. + * Also used for VP8 partitions. */ + RK_U32 size_tbl = MPP_ALIGN(sizeof(RK_U32) * (pre->height + 4), 8); + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_size_table_buf, size_tbl); + if (ret) { + mpp_err("hw_size_table_buf get failed ret %d\n", ret); + goto __ERR_RET; + } + } + { + RK_U32 cabac_tbl_size = 8 * 55 + 8 * 96; + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_cabac_table_buf, + cabac_tbl_size); + if (ret) { + mpp_err("hw_cabac_table_buf get failed\n"); + goto __ERR_RET; + } + } + hw_cfg->cabac_tbl_base = mpp_buffer_get_fd(buffers->hw_cabac_table_buf); + + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_mv_output_buf, + mb_total * 4); + if (ret) { + mpp_err("hw_mv_output_buf get failed ret %d\n", ret); + goto __ERR_RET; + } + + hw_cfg->mv_output_base = mpp_buffer_get_fd(buffers->hw_mv_output_buf); + + memset(mpp_buffer_get_ptr(buffers->hw_mv_output_buf), 0, sizeof(RK_U32) * mb_total); + + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_prob_count_buf, VP8_PROB_COUNT_BUF_SIZE); + if (ret) { + mpp_err("hw_prob_count_buf get failed ret %d\n", ret); + goto __ERR_RET; + } + + hw_cfg->prob_count_base = mpp_buffer_get_fd(buffers->hw_prob_count_buf); + { + /* VP8: Segmentation map, 4 bits/mb, 64-bit multiple. */ + RK_U32 segment_map_size = (mb_total * 4 + 63) / 64 * 8; + + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_segment_map_buf, segment_map_size); + if (ret) { + mpp_err("hw_segment_map_buf get failed ret %d\n", ret); + goto __ERR_RET; + } + + hw_cfg->segment_map_base = mpp_buffer_get_fd(buffers->hw_segment_map_buf); + memset(mpp_buffer_get_ptr(buffers->hw_segment_map_buf), 0, segment_map_size / 4); + + } + { + RK_U32 i = 0; + + ctx->picbuf.size = 1; + for (i = 0; i < 1; i++) + ctx->picbuf.ref_pic[i].picture.lum = mpp_buffer_get_fd(buffers->hw_luma_buf); + for (i = 0; i < 2; i++) + ctx->picbuf.ref_pic[i].picture.cb = mpp_buffer_get_fd(buffers->hw_cbcr_buf[i]); + } + { + RK_U32 pic_size = MPP_ALIGN(pre->width, 16) * MPP_ALIGN(pre->height, 16) * 3 / 2; + RK_U32 out_size = pic_size / 2; + + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_out_buf, out_size); + if (ret) { + mpp_err("hw_out_buf get failed ret %d\n", ret); + goto __ERR_RET; + } + } + ctx->regs = mpp_calloc(RK_U32, ctx->reg_size); + if (!ctx->regs) { + mpp_err("failed to calloc regs.\n"); + goto __ERR_RET; + } + + hw_cfg->intra_16_favor = -1; + hw_cfg->prev_mode_favor = -1; + hw_cfg->inter_favor = -1; + hw_cfg->skip_penalty = -1; + hw_cfg->diff_mv_penalty[0] = -1; + hw_cfg->diff_mv_penalty[1] = -1; + hw_cfg->diff_mv_penalty[2] = -1; + hw_cfg->split_penalty[0] = 0; + hw_cfg->split_penalty[1] = 0; + hw_cfg->split_penalty[2] = 0x3FF; + hw_cfg->split_penalty[3] = 0; + hw_cfg->zero_mv_favor = 0; + + hw_cfg->intra_area_top = hw_cfg->intra_area_bottom = 255; + hw_cfg->intra_area_left = hw_cfg->intra_area_right = 255; + hw_cfg->roi1_top = hw_cfg->roi1_bottom = 255; + hw_cfg->roi1_left = hw_cfg->roi1_right = 255; + hw_cfg->roi2_top = hw_cfg->roi2_bottom = 255; + hw_cfg->roi2_left = hw_cfg->roi2_right = 255; + + return ret; + +__ERR_RET: + if (buffers) + hal_vp8e_buf_free(hal); + + return ret; +} + +MPP_RET hal_vp8e_enc_strm_code(void *hal, HalTaskInfo *task) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + + MppEncCfgSet *cfg = ctx->cfg; + MppEncPrepCfg *prep = &cfg->prep; + + { + RK_U32 i = 0; + for (i = 0; i < 9; i++) { + ctx->p_out_buf[i] = NULL; + ctx->stream_size[i] = 0; + } + } + + { + HalEncTask *enc_task = &task->enc; + RK_U32 hor_stride = MPP_ALIGN(prep->width, 16); + RK_U32 ver_stride = MPP_ALIGN(prep->height, 16); + RK_U32 offset_uv = hor_stride * ver_stride; + + hw_cfg->input_lum_base = mpp_buffer_get_fd(enc_task->input); + hw_cfg->input_cb_base = hw_cfg->input_lum_base + (offset_uv << 10); + hw_cfg->input_cr_base = hw_cfg->input_cb_base + (offset_uv << 8); + } + + // split memory for vp8 partition + { + RK_S32 offset = 0; + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + RK_U8 *p_end = NULL; + RK_U32 buf_size = mpp_buffer_get_size(buffers->hw_out_buf); + RK_U32 bus_addr = mpp_buffer_get_fd(buffers->hw_out_buf); + RK_U8 *p_start = mpp_buffer_get_ptr(buffers->hw_out_buf); + + p_end = p_start + 3; + if (ctx->frame_type == VP8E_FRM_KEY) + p_end += 7;// frame tag len:I frame 10 byte, P frmae 3 byte. + vp8e_set_buffer(&ctx->bitbuf[0], p_start, p_end - p_start); + + offset = p_end - p_start; + hw_cfg->output_strm_base = bus_addr + (offset << 10); + + p_start = p_end; + p_end = p_start + buf_size / 10; + p_end = (RK_U8 *)((size_t)p_end & ~0x7); + vp8e_set_buffer(&ctx->bitbuf[1], p_start, p_end - p_start); + + offset += p_end - p_start; + hw_cfg->partition_Base[0] = bus_addr | (offset << 10); + + p_start = p_end; + p_end = mpp_buffer_get_ptr(buffers->hw_out_buf) + buf_size; + p_end = (RK_U8 *)((size_t)p_end & ~0x7); + vp8e_set_buffer(&ctx->bitbuf[2], p_start, p_end - p_start); + + offset += p_end - p_start; + hw_cfg->partition_Base[1] = bus_addr | (offset << 10); + hw_cfg->output_strm_size = p_end - p_start; + + p_start = p_end; + } + + { + + HalVp8ePicBuf *pic_buf = &ctx->picbuf; + pic_buf->cur_pic->show = 1; + pic_buf->cur_pic->poc = ctx->frame_cnt; + pic_buf->cur_pic->i_frame = (ctx->frame_type == VP8E_FRM_KEY); + + init_picbuf(ctx); + + if (ctx->frame_type == VP8E_FRM_P) { + pic_buf->cur_pic->p_frame = 1; + pic_buf->cur_pic->arf = 1; + pic_buf->cur_pic->grf = 1; + pic_buf->cur_pic->ipf = 1; + pic_buf->ref_pic_list[0].search = 1; + pic_buf->ref_pic_list[1].search = 1; + pic_buf->ref_pic_list[2].search = 1; + } + + if (ctx->rc->frame_coded == 0) + return MPP_OK; + + if (ctx->rc->golden_picture_rate) { + pic_buf->cur_pic->grf = 1; + if (!pic_buf->cur_pic->arf) + pic_buf->ref_pic_list[1].arf = 1; + } + } + set_frame_params(ctx); + set_picbuf_ref(ctx); + set_code_frame(ctx); + + return MPP_OK; +} + +MPP_RET hal_vp8e_init_qp_table(void *hal) +{ + RK_S32 i = 0, j = 0; + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + for (i = 0; i < QINDEX_RANGE; i++) { + RK_S32 tmp = 0; + Vp8eQp * qp = &ctx->qp_y1[i]; + for (j = 0; j < 2; j++) { + if (j == 0) { + tmp = dc_q_lookup_tbl[MPP_CLIP3(0, QINDEX_RANGE - 1, i)]; + } else { + tmp = ac_q_lookup_tbl[MPP_CLIP3(0, QINDEX_RANGE - 1, i)]; + } + + qp->quant[j] = MPP_MIN((1 << 16) / tmp, 0x3FFF); + qp->zbin[j] = ((q_zbin_factors_tbl[i] * tmp) + 64) >> 7; + qp->round[j] = (q_rounding_factors_tbl[i] * tmp) >> 7; + qp->dequant[j] = tmp; + } + + qp = &ctx->qp_y2[i]; + for (j = 0; j < 2; j++) { + if (j == 0) { + tmp = dc_q_lookup_tbl[MPP_CLIP3(0, QINDEX_RANGE - 1, i)]; + tmp = tmp * 2; + } else { + tmp = ac_q_lookup_tbl[MPP_CLIP3(0, QINDEX_RANGE - 1, i)]; + tmp = (tmp * 155) / 100; + if (tmp < 8) + tmp = 8; + } + qp->quant[j] = MPP_MIN((1 << 16) / tmp, 0x3FFF); + qp->zbin[j] = ((q_zbin_factors_tbl[i] * tmp) + 64) >> 7; + qp->round[j] = (q_rounding_factors_tbl[i] * tmp) >> 7; + qp->dequant[j] = tmp; + } + + qp = &ctx->qp_ch[i]; + for (j = 0; j < 2; j++) { + if (j == 0) { + tmp = dc_q_lookup_tbl[MPP_CLIP3(0, QINDEX_RANGE - 1, i)]; + if (tmp > 132) + tmp = 132; + } else { + tmp = ac_q_lookup_tbl[MPP_CLIP3(0, QINDEX_RANGE - 1, i)]; + } + qp->quant[j] = MPP_MIN((1 << 16) / tmp, 0x3FFF); + qp->zbin[j] = ((q_zbin_factors_tbl[i] * tmp) + 64) >> 7; + qp->round[j] = (q_rounding_factors_tbl[i] * tmp) >> 7; + qp->dequant[j] = tmp; + } + } + + return MPP_OK; +} + +MPP_RET hal_vp8e_update_buffers(void *hal, HalTaskInfo *task) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + const RK_U32 hw_offset = ctx->hw_cfg.first_free_bit / 8; + RK_U32 *part = (RK_U32 *)mpp_buffer_get_ptr(buffers->hw_size_table_buf); + + ctx->bitbuf[1].byte_cnt += part[0] - hw_offset; + ctx->bitbuf[1].data += part[0] - hw_offset; + + ctx->bitbuf[2].byte_cnt = part[1]; + ctx->bitbuf[2].data += part[1]; + ctx->bitbuf[3].byte_cnt = part[2]; + ctx->bitbuf[3].data += part[2]; + + set_frame_tag(ctx); + + if (vp8e_buffer_gap(&ctx->bitbuf[1], 4) == MPP_OK) { + set_data_part_size(ctx); + } + + ctx->prev_frame_lost = 0; + + ctx->p_out_buf[0] = (RK_U32 *)ctx->bitbuf[0].p_data; + ctx->p_out_buf[1] = (RK_U32 *)ctx->bitbuf[2].p_data; + if (ctx->sps.dct_partitions) + ctx->p_out_buf[2] = (RK_U32 *)ctx->bitbuf[3].p_data; + + ctx->stream_size[0] = ctx->bitbuf[0].byte_cnt + + ctx->bitbuf[1].byte_cnt; + ctx->stream_size[1] = ctx->bitbuf[2].byte_cnt; + + if (ctx->sps.dct_partitions) + ctx->stream_size[2] = ctx->bitbuf[3].byte_cnt; + + ctx->frame_size = ctx->stream_size[0] + ctx->stream_size[1] + + ctx->stream_size[2]; + + update_picbuf(&ctx->picbuf); + { + HalEncTask *enc_task = &task->enc; + RK_U8 *p_out = mpp_buffer_get_ptr(enc_task->output); + + if (ctx->frame_cnt == 0) { + write_ivf_header(hal, p_out); + + p_out += IVF_HDR_BYTES; + enc_task->length += IVF_HDR_BYTES; + } + + if (ctx->frame_size) { + write_ivf_frame(ctx, p_out); + + p_out += IVF_FRM_BYTES; + enc_task->length += IVF_FRM_BYTES; + } + + memcpy(p_out, ctx->p_out_buf[0], ctx->stream_size[0]); + p_out += ctx->stream_size[0]; + enc_task->length += ctx->stream_size[0]; + + memcpy(p_out, ctx->p_out_buf[1], ctx->stream_size[1]); + p_out += ctx->stream_size[1]; + enc_task->length += ctx->stream_size[1]; + + memcpy(p_out, ctx->p_out_buf[2], ctx->stream_size[2]); + p_out += ctx->stream_size[2]; + enc_task->length += ctx->stream_size[2]; + } + return MPP_OK; +} + +MPP_RET hal_vp8e_setup(void *hal) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + if (set_parameter(ctx)) { + mpp_err("set vp8e parameter failed"); + return MPP_NOK; + } + + if (set_picbuf(ctx)) { + mpp_err("set vp8e picbuf failed, no enough memory"); + return MPP_ERR_NOMEM; + } + + ret = alloc_buffer(ctx); + + return ret; +} + +MPP_RET hal_vp8e_buf_free(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + + if (buffers->hw_luma_buf) { + mpp_buffer_put(buffers->hw_luma_buf); + buffers->hw_luma_buf = NULL; + } + + { + RK_U32 i = 0; + for (i = 0; i < 2; i++) { + if (buffers->hw_cbcr_buf[i]) { + mpp_buffer_put(buffers->hw_cbcr_buf[i]); + buffers->hw_cbcr_buf[i] = NULL; + } + } + } + + if (buffers->hw_size_table_buf) { + mpp_buffer_put(buffers->hw_size_table_buf); + buffers->hw_size_table_buf = NULL; + } + + if (buffers->hw_cabac_table_buf) { + mpp_buffer_put(buffers->hw_cabac_table_buf); + buffers->hw_cabac_table_buf = NULL; + } + + if (buffers->hw_mv_output_buf) { + mpp_buffer_put(buffers->hw_mv_output_buf); + buffers->hw_mv_output_buf = NULL; + } + + if (buffers->hw_prob_count_buf) { + mpp_buffer_put(buffers->hw_prob_count_buf); + buffers->hw_prob_count_buf = NULL; + } + + if (buffers->hw_segment_map_buf) { + mpp_buffer_put(buffers->hw_segment_map_buf); + buffers->hw_segment_map_buf = NULL; + } + + if (buffers->hw_out_buf) { + mpp_buffer_put(buffers->hw_out_buf); + buffers->hw_out_buf = NULL; + } + + if (buffers->hw_buf_grp) { + mpp_buffer_group_put(buffers->hw_buf_grp); + buffers->hw_buf_grp = NULL; + } + + return MPP_OK; +} diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_base.h b/mpp/hal/vpu/vp8e/hal_vp8e_base.h new file mode 100644 index 00000000..33c4d788 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_base.h @@ -0,0 +1,391 @@ +/* + * 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_VP8E_BASE_H__ +#define __HAL_VP8E_BASE_H__ + +#include "rk_type.h" + +#include "mpp_device.h" +#include "mpp_hal.h" +#include "mpp_mem.h" + +#include "vpu.h" + +#include "hal_task.h" + +#include "vp8e_syntax.h" + +#include "hal_vp8e_entropy.h" +#include "hal_vp8e_putbit.h" + +#define VP8_PROB_COUNT_MV_OFFSET (222) +#define VP8_PROB_COUNT_BUF_SIZE (244*2) + +#define mask_7b (RK_U32)0x0000007F + +#define INPUT_YUV420PLANAR 0x00 +#define INPUT_YUV420SEMIPLANAR 0x01 +#define INPUT_YUYV422INTERLEAVED 0x02 +#define INPUT_UYVY422INTERLEAVED 0x03 +#define INPUT_RGB565 0x04 +#define INPUT_RGB555 0x05 +#define INPUT_RGB444 0x06 +#define INPUT_RGB888 0x07 +#define INPUT_RGB101010 0x08 +#define INPUT_YUYV422TILED 0x09 + +#define IVF_HDR_BYTES 32 +#define IVF_FRM_BYTES 12 + +typedef enum vp8_frm_type_e { + VP8E_FRM_KEY = 0, + VP8E_FRM_P, +} Vp8FrmType; + +typedef struct vp8e_hal_vpu_buffers_t { + MppBufferGroup hw_buf_grp; + + MppBuffer hw_rec_buf[2]; + MppBuffer hw_luma_buf; + MppBuffer hw_cbcr_buf[2]; + MppBuffer hw_cabac_table_buf; + MppBuffer hw_size_table_buf; + MppBuffer hw_segment_map_buf; + MppBuffer hw_prob_count_buf; + MppBuffer hw_mv_output_buf; + MppBuffer hw_out_buf; +} Vp8eVpuBuf; + +#define PENALTY_TABLE_SIZE 128 + +/** + * pps definition + */ + +#define SGM_CNT 4 + +typedef struct sgm_t { + RK_U8 map_modified; + RK_S32 id_cnt[SGM_CNT]; +} Sgm; + +typedef struct { + Sgm sgm; + RK_S32 qp; + RK_U8 segment_enabled; + RK_S32 qp_sgm[SGM_CNT]; + RK_S32 level_sgm[SGM_CNT]; +} Pps; + +typedef struct { + Pps *store; + RK_S32 size; + Pps *pps; + Pps *prev_pps; + RK_S32 qp_sgm[SGM_CNT]; + RK_S32 level_sgm[SGM_CNT]; +} Vp8ePps; + + +/** + * QP definition + */ + +#define QINDEX_RANGE 128 + +typedef struct { + RK_S32 quant[2]; + RK_S32 zbin[2]; + RK_S32 round[2]; + RK_S32 dequant[2]; +} Vp8eQp; + +/** + * sps definition + */ + +typedef struct vp8e_sps_t { + RK_S32 pic_width_in_mbs; + RK_S32 pic_height_in_mbs; + RK_S32 pic_width_in_pixel; + RK_S32 pic_height_in_pixel; + RK_S32 horizontal_scaling; + RK_S32 vertical_scaling; + RK_S32 color_type; + RK_S32 clamp_type; + RK_S32 dct_partitions; + RK_S32 partition_cnt; + RK_S32 profile; + RK_S32 filter_type; + RK_S32 filter_level; + RK_S32 filter_sharpness; + RK_S32 quarter_pixel_mv; + RK_S32 split_mv; + RK_S32 sing_bias[3]; + + RK_S32 auto_filter_level; + RK_S32 auto_filter_sharpness; + RK_U8 filter_delta_enable; + RK_S32 mode_delta[4]; + RK_S32 old_mode_delta[4]; + RK_S32 ref_delta[4]; + RK_S32 old_ref_delta[4]; + RK_S32 refresh_entropy; +} Vp8eSps; + +/** + * entropy definition + */ + +typedef struct vp8e_hal_entropy_t { + RK_S32 skip_false_prob; + RK_S32 intra_prob; + RK_S32 last_prob; + RK_S32 gf_prob; + RK_S32 kf_y_mode_prob[4]; + RK_S32 y_mode_prob[4]; + RK_S32 kf_uv_mode_prob[3]; + RK_S32 uv_mode_prob[3]; + RK_S32 kf_b_mode_prob[10][10][9]; + RK_S32 b_mode_prob[9]; + RK_S32 coeff_prob[4][8][3][11]; + RK_S32 old_coeff_prob[4][8][3][11]; + RK_S32 mv_ref_prob[4]; + RK_S32 mv_prob[2][19]; + RK_S32 old_mv_prob[2][19]; + RK_S32 sub_mv_partprob[3]; + RK_S32 sub_mv_ref_prob[5][3]; + RK_S32 default_coeff_prob_flag; + RK_S32 update_coeff_prob_flag; + RK_S32 segment_prob[3]; +} Vp8eHalEntropy; + +/** + * picture definition + */ + +#define REF_FRAME_COUNT 3 + +typedef struct { + RK_S32 lum_width; + RK_S32 lum_height; + RK_S32 ch_width; + RK_S32 ch_height; + RK_U32 lum; + RK_U32 cb; +} HalVp8ePic; + +typedef struct hal_vp8e_refpic_t { + HalVp8ePic picture; + Vp8eHalEntropy *entropy; + RK_S32 poc; + + RK_U8 i_frame; + RK_U8 p_frame; + RK_U8 show; + RK_U8 ipf; + RK_U8 arf; + RK_U8 grf; + RK_U8 search; + struct hal_vp8e_refpic_t *refPic; +} HalVp8eRefPic; + +typedef struct { + RK_S32 size; /* Amount of allocated reference pictures */ + HalVp8ePic input; /* Input picture */ + HalVp8eRefPic ref_pic[REF_FRAME_COUNT + 1]; /* Reference picture store */ + HalVp8eRefPic ref_pic_list[REF_FRAME_COUNT]; /* Reference picture list */ + HalVp8eRefPic *cur_pic; /* Pointer to picture under reconstruction */ + HalVp8eRefPic *last_pic; /* Last picture */ +} HalVp8ePicBuf; + +typedef struct { + RK_U32 irq_disable; + RK_U32 mbs_in_col; + RK_U32 mbs_in_row; + RK_U32 rounding_ctrl; + RK_U32 frame_coding_type; + RK_U32 coding_type; + RK_U32 pixels_on_row; + RK_U32 x_fill; + RK_U32 y_fill; + RK_U32 filter_disable; + RK_U32 enable_cabac; + RK_U32 input_format; + RK_U32 input_rotation; + RK_U32 output_strm_base; + RK_U32 output_strm_size; + RK_U32 first_free_bit; + RK_U32 strm_start_msb; + RK_U32 strm_start_lsb; + RK_U32 size_tbl_base; + RK_U32 int_slice_ready; + RK_U32 rec_write_disable; + RK_U32 recon_img_id; + RK_U32 internal_img_lum_base_w; + RK_U32 internal_img_chr_base_w; + RK_U32 internal_img_lum_base_r[2]; + RK_U32 internal_img_chr_base_r[2]; + RK_U32 input_lum_base; + RK_U32 input_cb_base; + RK_U32 input_cr_base; + RK_U32 cp_distance_mbs; //TODO maybe useless + RK_U32 rlc_count; //TODO read from reg + RK_U32 qp_sum; //TODO read from reg + RK_U8 dmv_penalty[PENALTY_TABLE_SIZE]; + RK_U8 dmv_qpel_penalty[PENALTY_TABLE_SIZE]; + RK_U32 input_luma_base_offset; + RK_U32 input_chroma_base_offset; + RK_U32 disable_qp_mv; + RK_U32 vs_next_luma_base; + RK_U32 vs_mode; + RK_U32 asic_cfg_reg; + RK_S32 intra_16_favor; + RK_S32 prev_mode_favor; + RK_S32 inter_favor; + RK_S32 skip_penalty; + RK_S32 golden_penalty; + RK_S32 diff_mv_penalty[3]; + RK_U32 mad_count; + RK_U32 cir_start; + RK_U32 cir_interval; + RK_U32 intra_area_top; + RK_U32 intra_area_left; + RK_U32 intra_area_bottom; + RK_U32 intra_area_right; + RK_U32 roi1_top; + RK_U32 roi1_left; + RK_U32 roi1_bottom; + RK_U32 roi1_right; + RK_U32 roi2_top; + RK_U32 roi2_left; + RK_U32 roi2_bottom; + RK_U32 roi2_right; + RK_S32 roi1_delta_qp; + RK_S32 roi2_delta_qp; + RK_U32 mv_output_base; + RK_U32 cabac_tbl_base; + RK_U32 prob_count_base; + RK_U32 segment_map_base; + RK_U16 rgb_coeff_a; + RK_U16 rgb_coeff_b; + RK_U16 rgb_coeff_c; + RK_U16 rgb_coeff_e; + RK_U16 rgb_coeff_f; + RK_U8 r_mask_msb; + RK_U8 g_mask_msb; + RK_U8 b_mask_msb; + RK_U32 partition_Base[8]; + RK_U16 y1_quant_dc[4]; + RK_U16 y1_quant_ac[4]; + RK_U16 y2_quant_dc[4]; + RK_U16 y2_quant_ac[4]; + RK_U16 ch_quant_dc[4]; + RK_U16 ch_quant_ac[4]; + RK_U16 y1_zbin_dc[4]; + RK_U16 y1_zbin_ac[4]; + RK_U16 y2_zbin_dc[4]; + RK_U16 y2_zbin_ac[4]; + RK_U16 ch_zbin_dc[4]; + RK_U16 ch_zbin_ac[4]; + RK_U8 y1_round_dc[4]; + RK_U8 y1_round_ac[4]; + RK_U8 y2_round_dc[4]; + RK_U8 y2_round_ac[4]; + RK_U8 ch_round_dc[4]; + RK_U8 ch_round_ac[4]; + RK_U16 y1_dequant_dc[4]; + RK_U16 y1_dequant_ac[4]; + RK_U16 y2_dequant_dc[4]; + RK_U16 y2_dequant_ac[4]; + RK_U16 ch_dequant_dc[4]; + RK_U16 ch_dequant_ac[4]; + RK_U32 segment_enable; + RK_U32 segment_map_update; + RK_U32 mv_ref_idx[2]; + RK_U32 ref2_enable; + RK_U32 bool_enc_value; + RK_U32 bool_enc_value_bits; + RK_U32 bool_enc_range; + RK_U32 dct_partitions; + RK_U32 filter_level[4]; + RK_U32 filter_sharpness; + RK_U32 intra_mode_penalty[4]; + RK_U32 intra_b_mode_penalty[10]; + RK_U32 zero_mv_favor; + RK_U32 split_mv_mode; + RK_U32 split_penalty[4]; + RK_S32 lf_ref_delta[4]; + RK_S32 lf_mode_delta[4]; +} Vp8eHwCfg; + +typedef struct hal_vp8e_ctx_s { + IOInterruptCB int_cb; + Vp8eFeedback feedback; + MppDevCtx dev_ctx; + + void *regs; + void *buffers; + RK_U32 reg_size; + + MppEncCfgSet *cfg; + MppEncCfgSet *set; + + MppHalApi hal_api; + + Vp8eSps sps; + Vp8ePps ppss; + //TODO remove vp8_rc + Vp8eRc *rc; + Vp8eHwCfg hw_cfg; + Vp8eHalEntropy entropy; + HalVp8ePicBuf picbuf; + Vp8ePutBitBuf bitbuf[4]; + Vp8eQp qp_y1[QINDEX_RANGE]; + Vp8eQp qp_y2[QINDEX_RANGE]; + Vp8eQp qp_ch[QINDEX_RANGE]; + RK_U32 prev_frame_lost; + RK_U32 *p_out_buf[9]; + RK_U32 stream_size[9]; + RK_U32 frame_size; + + RK_U32 buffer_ready; + RK_U64 frame_cnt; + RK_U8 key_frm_next; + RK_U32 gop_len; + RK_U32 bit_rate; + Vp8FrmType frame_type; + + RK_U32 mb_per_frame; + RK_U32 mb_per_row; + RK_U32 mb_per_col; +} HalVp8eCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET hal_vp8e_update_buffers(void *hal, HalTaskInfo *task); +MPP_RET hal_vp8e_enc_strm_code(void *hal, HalTaskInfo *info); +MPP_RET hal_vp8e_init_qp_table(void *hal); +MPP_RET hal_vp8e_setup(void *hal); +MPP_RET hal_vp8e_buf_free(void *hal); +#ifdef __cplusplus +} +#endif + +#endif /*__HAL_VP*E_BASE_H__*/ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_debug.h b/mpp/hal/vpu/vp8e/hal_vp8e_debug.h new file mode 100644 index 00000000..93190130 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_debug.h @@ -0,0 +1,56 @@ +/* + * 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_VP8E_DEBUG_H__ +#define __HAL_VP8E_DEBUG_H__ + +#include "mpp_log.h" + +#define VP8E_DBG_HAL_FUNCTION (0x00000001) +#define VP8E_DBG_HAL_REG (0x00000002) +#define VP8E_DBG_HAL_DUMP_REG (0x00000004) +#define VP8E_DBG_HAL_IRQ (0x00000008) +#define VP8E_DBG_HAL_DUMP_IVF (0x00000010) + +#define VP8E_DBG(flag, fmt, ...) _mpp_dbg(vp8e_hal_debug, flag, fmt, ## __VA_ARGS__) +#define VP8E_DBG_F(flag, fmt, ...) _mpp_dbg_f(vp8e_hal_debug, flag, fmt, ## __VA_ARGS__) + +#define vp8e_hal_err(fmt, ...) \ + do {\ + mpp_err_f(fmt, ## __VA_ARGS__);\ + } while (0) + +#define vp8e_hal_dbg(type, fmt, ...) \ + do {\ + if (vp8e_hal_debug & type)\ + mpp_log(fmt, ## __VA_ARGS__);\ + } while (0) + +#define vp8e_hal_enter() \ + do {\ + if (vp8e_hal_debug & VP8E_DBG_HAL_FUNCTION)\ + mpp_log("line(%d), func(%s), enter", __LINE__, __FUNCTION__);\ + } while (0) + +#define vp8e_hal_leave() \ + do {\ + if (vp8e_hal_debug & VP8E_DBG_HAL_FUNCTION)\ + mpp_log("line(%d), func(%s), leave", __LINE__, __FUNCTION__);\ + } while (0) + +extern RK_U32 vp8e_hal_debug; + +#endif /*__HAL_VP8E_DEBUG_H__*/ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_entropy.c b/mpp/hal/vpu/vp8e/hal_vp8e_entropy.c new file mode 100644 index 00000000..38d647b5 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_entropy.c @@ -0,0 +1,430 @@ +/* + * 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_vp8e_entropy" + +#include + +#include "mpp_common.h" + +#include "hal_vp8e_base.h" +#include "hal_vp8e_entropy.h" +#include "hal_vp8e_putbit.h" +#include "hal_vp8e_table.h" + +#define COST_BOOL(prob, bin)\ + ((bin) ? vp8_prob_cost_tbl[255 - (prob)] : vp8_prob_cost_tbl[prob]) + +static RK_U32 calc_mvprob(RK_U32 left, RK_U32 right, RK_U32 prob) +{ + RK_U32 p; + + if (left + right) { + p = (left * 255) / (left + right); + p &= -2; + if (!p) + p = 1; + } else + p = prob; + + return p; +} + +static RK_U32 update_prob(RK_U32 prob, RK_U32 left, RK_U32 right, + RK_U32 old_prob, RK_U32 new_prob, RK_U32 fixed) +{ + RK_S32 u, s; + + u = (RK_S32)fixed + ((vp8_prob_cost_tbl[255 - prob] - vp8_prob_cost_tbl[prob]) >> 8); + s = ((RK_S32)left * (vp8_prob_cost_tbl[old_prob] - vp8_prob_cost_tbl[new_prob]) + + (RK_S32)right * (vp8_prob_cost_tbl[255 - old_prob] - vp8_prob_cost_tbl[255 - new_prob])) >> 8; + + return (s > u); +} + +static RK_S32 get_cost_tree(Vp8eTree const *tree, RK_S32 *prob) +{ + RK_S32 bit_cost = 0; + RK_S32 value = tree->value; + RK_S32 number = tree->number; + RK_S32 const *index = tree->index; + + while (number--) { + bit_cost += COST_BOOL(prob[*index++], (value >> number) & 1); + } + + return bit_cost; +} + +MPP_RET vp8e_init_entropy(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + Vp8eHalEntropy *entropy = &ctx->entropy; + + entropy->update_coeff_prob_flag = 0; + if (!ctx->sps.refresh_entropy || ctx->picbuf.cur_pic->i_frame) { + if (!entropy->default_coeff_prob_flag) { + memcpy(entropy->coeff_prob, default_prob_coeff_tbl, sizeof(default_prob_coeff_tbl)); + entropy->update_coeff_prob_flag = 1; + } + memcpy(entropy->mv_prob, default_prob_mv_tbl, sizeof(default_prob_mv_tbl)); + entropy->default_coeff_prob_flag = 1; + } + + memcpy(entropy->old_coeff_prob, entropy->coeff_prob, sizeof(entropy->coeff_prob)); + if (ctx->frame_cnt == 0 || ctx->key_frm_next) + memcpy(entropy->old_mv_prob, entropy->mv_prob, sizeof(entropy->mv_prob)); + + entropy->skip_false_prob = default_skip_false_prob_tbl[ctx->rc->qp_hdr]; + + if (ctx->frame_cnt == 0) + return MPP_OK; + + if ((!ctx->picbuf.cur_pic->ipf) && (!ctx->picbuf.cur_pic->grf) && + (!ctx->picbuf.cur_pic->arf)) + return MPP_OK; + + if (ctx->prev_frame_lost) + return MPP_OK; + { + RK_S32 i, j, k, l; + + RK_U32 p, left, right; + RK_U32 old_p, upd_p = 0; + + RK_U32 type; + RK_U32 branch_cnt[2]; + RK_U16 *p_tmp = NULL; + + RK_U16 *p_cnt = (RK_U16 *)mpp_buffer_get_ptr(buffers->hw_prob_count_buf); + + for (i = 0; i < 4; i++) { + for (j = 0; j < 7; j++) { + for (k = 0; k < 3; k++) { + RK_S32 tmp, ii; + + tmp = i * 7 * 3 + j * 3 + k; + tmp += 2 * 4 * 7 * 3; + ii = offset_tbl[tmp]; + + right = ii >= 0 ? p_cnt[ii] : 0; + + for (l = 2; l--;) { + old_p = entropy->coeff_prob[i][j][k][l]; + old_p = coeff_update_prob_tbl[i][j][k][l]; + + tmp -= 4 * 7 * 3; + ii = offset_tbl[tmp]; + left = ii >= 0 ? p_cnt[ii] : 0; + if (left + right) { + p = ((left * 256) + ((left + right) >> 1)) / (left + right); + if (p > 255) p = 255; + } else + p = old_p; + + if (update_prob(upd_p, left, right, old_p, p, 8)) { + entropy->coeff_prob[i][j][k][l] = p; + entropy->update_coeff_prob_flag = 1; + } + right += left; + } + } + } + } + + if (entropy->update_coeff_prob_flag) + entropy->default_coeff_prob_flag = 0; + + p_tmp = p_cnt + VP8_PROB_COUNT_MV_OFFSET; + for (i = 0; i < 2; i++) { + left = *p_tmp++; + right = *p_tmp++; + + p = calc_mvprob(left, right, entropy->old_mv_prob[i][0]); + + if (update_prob(mv_update_prob_tbl[i][0], left, right, + entropy->old_mv_prob[i][0], p, 6)) + entropy->mv_prob[i][0] = p; + + right += left; + left = *p_tmp++; + right -= left - p_tmp[0]; + + p = calc_mvprob(left, right, entropy->old_mv_prob[i][1]); + if (update_prob(mv_update_prob_tbl[i][1], left, right, + entropy->old_mv_prob[i][1], p, 6)) + entropy->mv_prob[i][1] = p; + + for (j = 0; j < 2; j++) { + left = *p_tmp++; + right = *p_tmp++; + p = calc_mvprob(left, right, entropy->old_mv_prob[i][4 + j]); + if (update_prob(mv_update_prob_tbl[i][4 + j], left, right, + entropy->old_mv_prob[i][4 + j], p, 6)) + entropy->mv_prob[i][4 + j] = p; + branch_cnt[j] = left + right; + } + + p = calc_mvprob(branch_cnt[0], branch_cnt[1], entropy->old_mv_prob[i][3]); + if (update_prob(mv_update_prob_tbl[i][3], branch_cnt[0], branch_cnt[1], + entropy->old_mv_prob[i][3], p, 6)) + entropy->mv_prob[i][3] = p; + + type = branch_cnt[0] + branch_cnt[1]; + + for (j = 0; j < 2; j++) { + left = *p_tmp++; + right = *p_tmp++; + p = calc_mvprob(left, right, entropy->old_mv_prob[i][7 + j]); + if (update_prob(mv_update_prob_tbl[i][7 + j], left, right, + entropy->old_mv_prob[i][7 + j], p, 6)) + entropy->mv_prob[i][7 + j] = p; + branch_cnt[j] = left + right; + } + + p = calc_mvprob(branch_cnt[0], branch_cnt[1], entropy->old_mv_prob[i][6]); + if (update_prob(mv_update_prob_tbl[i][6], branch_cnt[0], branch_cnt[1], + entropy->old_mv_prob[i][6], p, 6)) + entropy->mv_prob[i][6] = p; + + p = calc_mvprob(type, branch_cnt[0] + branch_cnt[1], + entropy->old_mv_prob[i][2]); + if (update_prob(mv_update_prob_tbl[i][2], type, branch_cnt[0] + branch_cnt[1], + entropy->old_mv_prob[i][2], p, 6)) + entropy->mv_prob[i][2] = p; + } + } + { + entropy->last_prob = 255; + entropy->gf_prob = 128; + memcpy(entropy->y_mode_prob, y_mode_prob_tbl, sizeof(y_mode_prob_tbl)); + memcpy(entropy->uv_mode_prob, uv_mode_prob_tbl, sizeof(uv_mode_prob_tbl)); + } + return MPP_OK; +} + +MPP_RET vp8e_swap_endian(RK_U32 *buf, RK_U32 bytes) +{ + RK_U32 i = 0; + RK_S32 words = bytes / 4; + + while (words > 0) { + RK_U32 val = buf[i]; + RK_U32 tmp = 0; + + tmp |= (val & 0xFF) << 24; + tmp |= (val & 0xFF00) << 8; + tmp |= (val & 0xFF0000) >> 8; + tmp |= (val & 0xFF000000) >> 24; + + { + RK_U32 val2 = buf[i + 1]; + RK_U32 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++; + } + return MPP_OK; +} + + +MPP_RET vp8e_write_entropy_tables(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + Vp8eHalEntropy *entropy = &ctx->entropy; + + RK_U8 *table = (RK_U8 *)mpp_buffer_get_ptr(buffers->hw_cabac_table_buf); + /* Write probability tables to ASIC linear memory, reg + mem */ + memset(table, 0, 56); // use 56 bytes + table[0] = entropy->skip_false_prob; + table[1] = entropy->intra_prob; + table[2] = entropy->last_prob; + table[3] = entropy->gf_prob; + table[4] = entropy->segment_prob[0]; + table[5] = entropy->segment_prob[1]; + table[6] = entropy->segment_prob[2]; + + table[8] = entropy->y_mode_prob[0]; + table[9] = entropy->y_mode_prob[1]; + table[10] = entropy->y_mode_prob[2]; + table[11] = entropy->y_mode_prob[3]; + table[12] = entropy->uv_mode_prob[0]; + table[13] = entropy->uv_mode_prob[1]; + table[14] = entropy->uv_mode_prob[2]; + + /* MV probabilities x+y: short, sign, size 8-9 */ + table[16] = entropy->mv_prob[1][0]; + table[17] = entropy->mv_prob[0][0]; + table[18] = entropy->mv_prob[1][1]; + table[19] = entropy->mv_prob[0][1]; + table[20] = entropy->mv_prob[1][17]; + table[21] = entropy->mv_prob[1][18]; + table[22] = entropy->mv_prob[0][17]; + table[23] = entropy->mv_prob[0][18]; + { + RK_S32 i, j, k, l; + /* MV X size */ + for (i = 0; i < 8; i++) + table[24 + i] = entropy->mv_prob[1][9 + i]; + + /* MV Y size */ + for (i = 0; i < 8; i++) + table[32 + i] = entropy->mv_prob[0][9 + i]; + + /* MV X short tree */ + for (i = 0; i < 7; i++) + table[40 + i] = entropy->mv_prob[1][2 + i]; + + /* MV Y short tree */ + for (i = 0; i < 7; i++) + table[48 + i] = entropy->mv_prob[0][2 + i]; + + /* Update the ASIC table when needed. */ + if (entropy->update_coeff_prob_flag) { + table += 56; + /* DCT coeff probabilities 0-2, two fields per line. */ + for (i = 0; i < 4; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 3; k++) { + for (l = 0; l < 3; l++) { + *table++ = entropy->coeff_prob[i][j][k][l]; + } + *table++ = 0; + } + + /* ASIC second probability table in ext mem. + * DCT coeff probabilities 4 5 6 7 8 9 10 3 on each line. + * coeff 3 was moved from first table to second so it is last. */ + for (i = 0; i < 4; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 3; k++) { + for (l = 4; l < 11; l++) { + *table++ = entropy->coeff_prob[i][j][k][l]; + } + *table++ = entropy->coeff_prob[i][j][k][3]; + } + } + } + table = mpp_buffer_get_ptr(buffers->hw_cabac_table_buf); + if (entropy->update_coeff_prob_flag) + vp8e_swap_endian((RK_U32 *) table, 56 + 8 * 48 + 8 * 96); + else + vp8e_swap_endian((RK_U32 *) table, 56); + + return MPP_OK; +} + +RK_S32 vp8e_calc_cost_mv(RK_S32 mvd, RK_S32 *mv_prob) +{ + RK_S32 i = 0; + RK_S32 bit_cost = 0; + + RK_S32 tmp = MPP_ABS(mvd >> 1); + + if (tmp < 8) { + bit_cost += COST_BOOL(mv_prob[0], 0); + bit_cost += get_cost_tree(&mv_tree_tbl[tmp], mv_prob + 2); + if (!tmp) + return bit_cost; + + /* Sign */ + bit_cost += COST_BOOL(mv_prob[1], mvd < 0); + return bit_cost; + } + + bit_cost += COST_BOOL(mv_prob[0], 1); + + for (i = 0; i < 3; i++) { + bit_cost += COST_BOOL(mv_prob[9 + i], (tmp >> i) & 1); + } + + for (i = 9; i > 3; i--) { + bit_cost += COST_BOOL(mv_prob[9 + i], (tmp >> i) & 1); + } + + if (tmp > 15) { + bit_cost += COST_BOOL(mv_prob[9 + 3], (tmp >> 3) & 1); + } + + bit_cost += COST_BOOL(mv_prob[1], mvd < 0); + + return bit_cost; +} + +MPP_RET vp8e_calc_coeff_prob(Vp8ePutBitBuf *bitbuf, RK_S32 (*curr)[4][8][3][11], + RK_S32 (*prev)[4][8][3][11]) +{ + RK_S32 i, j, k, l; + RK_S32 prob, new, old; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 8; j++) { + for (k = 0; k < 3; k++) { + for (l = 0; l < 11; l++) { + prob = coeff_update_prob_tbl[i][j][k][l]; + old = (RK_S32) (*prev)[i][j][k][l]; + new = (RK_S32) (*curr)[i][j][k][l]; + + if (new == old) { + vp8e_put_bool(bitbuf, prob, 0); + } else { + vp8e_put_bool(bitbuf, prob, 1); + vp8e_put_lit(bitbuf, new, 8); + } + } + } + } + } + return MPP_OK; +} + +MPP_RET vp8e_calc_mv_prob(Vp8ePutBitBuf *bitbuf, RK_S32 (*curr)[2][19], + RK_S32 (*prev)[2][19]) +{ + RK_S32 i, j; + RK_S32 prob, new, old; + + for (i = 0; i < 2; i++) { + for (j = 0; j < 19; j++) { + prob = mv_update_prob_tbl[i][j]; + old = (RK_S32) (*prev)[i][j]; + new = (RK_S32) (*curr)[i][j]; + + if (new == old) { + vp8e_put_bool(bitbuf, prob, 0); + } else { + vp8e_put_bool(bitbuf, prob, 1); + vp8e_put_lit(bitbuf, new >> 1, 7); + } + } + } + return MPP_OK; +} diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_entropy.h b/mpp/hal/vpu/vp8e/hal_vp8e_entropy.h new file mode 100644 index 00000000..7f599650 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_entropy.h @@ -0,0 +1,41 @@ +/* + * 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_VP8E_ENTROPY_H__ +#define __HAL_VP8E_ENTROPY_H__ + +#include "rk_type.h" + +#include "hal_vp8e_putbit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vp8e_init_entropy(void *hal); +MPP_RET vp8e_write_entropy_tables(void *hal); +RK_S32 vp8e_calc_cost_mv(RK_S32 mvd, RK_S32 *mv_prob); +MPP_RET vp8e_calc_coeff_prob(Vp8ePutBitBuf *bitbuf, + RK_S32 (*curr)[4][8][3][11], RK_S32 (*prev)[4][8][3][11]); +MPP_RET vp8e_calc_mv_prob(Vp8ePutBitBuf *bitbuf, + RK_S32 (*curr)[2][19], RK_S32 (*prev)[2][19]); +MPP_RET vp8e_swap_endian(RK_U32 *buf, RK_U32 bytes); + +#ifdef __cplusplus +} +#endif + +#endif /*__HAL_VP8E_ENTROPY_H__*/ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_putbit.c b/mpp/hal/vpu/vp8e/hal_vp8e_putbit.c new file mode 100644 index 00000000..1fa5b29b --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_putbit.c @@ -0,0 +1,114 @@ +/* + * 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_vp8e_putbit" + +#include "hal_vp8e_base.h" +#include "hal_vp8e_putbit.h" + +#define TRACE_BIT_STREAM(v,n) + + +MPP_RET vp8e_set_buffer(Vp8ePutBitBuf *bitbuf, RK_U8 *data, RK_S32 size) +{ + if ((bitbuf == NULL) || (data == NULL) || (size < 1)) + return MPP_NOK; + + bitbuf->data = data; + bitbuf->p_data = data; + bitbuf->size = size; + + bitbuf->range = 255; + bitbuf->bottom = 0; + bitbuf->bits_left = 24; + + bitbuf->byte_cnt = 0; + + return MPP_OK; +} + +MPP_RET vp8e_put_bool(Vp8ePutBitBuf *bitbuf, RK_S32 prob, RK_S32 bool_value) +{ + RK_S32 bits = 0; + RK_S32 length_bits = 0; + + RK_S32 split = 1 + ((bitbuf->range - 1) * prob >> 8); + + if (bool_value) { + bitbuf->bottom += split; + bitbuf->range -= split; + } else { + bitbuf->range = split; + } + + while (bitbuf->range < 128) { + if (bitbuf->bottom < 0) { + RK_U8 *data = bitbuf->data; + while (*--data == 255) { + *data = 0; + } + (*data)++; + } + bitbuf->range <<= 1; + bitbuf->bottom <<= 1; + + if (!--bitbuf->bits_left) { + length_bits += 8; + bits <<= 8; + bits |= (bitbuf->bottom >> 24) & 0xff; + TRACE_BIT_STREAM(bits & 0xff, 8); + *bitbuf->data++ = (bitbuf->bottom >> 24) & 0xff; + bitbuf->byte_cnt++; + bitbuf->bottom &= 0xffffff; /* Keep 3 bytes */ + bitbuf->bits_left = 8; + } + } + return MPP_OK; +} + +MPP_RET vp8e_put_lit(Vp8ePutBitBuf *bitbuf, RK_S32 value, + RK_S32 number) +{ + while (number--) { + vp8e_put_bool(bitbuf, 128, (value >> number) & 0x1); + } + return MPP_OK; +} + +MPP_RET vp8e_put_byte(Vp8ePutBitBuf *bitbuf, RK_S32 byte) +{ + *bitbuf->data++ = byte; + bitbuf->byte_cnt++; + return MPP_OK; +} + +MPP_RET vp8e_buffer_gap(Vp8ePutBitBuf *bitbuf, RK_S32 gap) +{ + if ((bitbuf->data - bitbuf->p_data) + gap > bitbuf->size) { + bitbuf->size = 0; + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET vp8e_buffer_overflow(Vp8ePutBitBuf *bitbuf) +{ + if (bitbuf->size > 0) + return MPP_OK; + + return MPP_NOK; +} diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_putbit.h b/mpp/hal/vpu/vp8e/hal_vp8e_putbit.h new file mode 100644 index 00000000..a41baaf9 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_putbit.h @@ -0,0 +1,55 @@ +/* + * 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_VP8E_PUT_BIT_H__ +#define __HAL_VP8E_PUT_BIT_H__ + +#include "rk_type.h" +#include "mpp_err.h" + +typedef struct { + RK_U8 *data; + RK_U8 *p_data; + RK_S32 size; + RK_S32 byte_cnt; + + RK_S32 range; + RK_S32 bottom; + RK_S32 bits_left; +} Vp8ePutBitBuf; + +typedef struct { + RK_S32 value; + RK_S32 number; + RK_S32 index[9]; +} Vp8eTree; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vp8e_put_lit(Vp8ePutBitBuf *bitbuf, RK_S32 value, RK_S32 number); +MPP_RET vp8e_buffer_gap(Vp8ePutBitBuf *bitbuf, RK_S32 gap); +MPP_RET vp8e_buffer_overflow(Vp8ePutBitBuf *bitbuf); +MPP_RET vp8e_put_byte(Vp8ePutBitBuf *bitbuf, RK_S32 byte); +MPP_RET vp8e_put_bool(Vp8ePutBitBuf *bitbuf, RK_S32 prob, RK_S32 boolValue); +MPP_RET vp8e_set_buffer(Vp8ePutBitBuf *bitbuf, RK_U8 *data, RK_S32 size); + +#ifdef __cplusplus +} +#endif + +#endif /*__HAL_VP8E_PUTBIT_H__*/ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_table.c b/mpp/hal/vpu/vp8e/hal_vp8e_table.c new file mode 100644 index 00000000..2779cadd --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_table.c @@ -0,0 +1,590 @@ +/* + * 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 "hal_vp8e_table.h" + +RK_S32 const default_prob_coeff_tbl[4][8][3][11] = { + { + { + {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, + {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, + {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128} + }, + { + {253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128}, + {189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128}, + {106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128} + }, + { + { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, + {181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128}, + { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 } + }, + { + { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, + {184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128}, + { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 } + }, + { + { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, + {170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128}, + { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 } + }, + { + { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, + {207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128}, + {102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128} + }, + { + { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, + {177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128}, + { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 } + }, + { + { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + {246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}, + {255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128} + } + }, + { + { + {198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62}, + {131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1}, + { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 } + }, + { + { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, + {184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128}, + { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 } + }, + { + { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, + { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, + { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 } + }, + { + { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, + {109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128}, + { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 } + }, + { + { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, + { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, + { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 } + }, + { + { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, + {124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128}, + { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 } + }, + { + { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, + {121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128}, + { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 } + }, + { + { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, + {203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128}, + {137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128} + } + }, + { + { + {253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128}, + {175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128}, + { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 } + }, + { + { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, + {239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128}, + {155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128} + }, + { + { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, + {201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128}, + { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 } + }, + { + { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, + {223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128}, + {141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128} + }, + { + { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + {190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128}, + {149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128} + }, + { + { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + {247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128}, + {240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128} + }, + { + { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, + {213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128}, + { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { + {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, + {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, + {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128} + } + }, + { + { + {202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255}, + {126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128}, + { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 } + }, + { + { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, + {166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128}, + { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 } + }, + { + { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, + {124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128}, + { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 } + }, + { + { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, + {149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128}, + { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 } + }, + { + { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, + {123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128}, + { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 } + }, + { + { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, + {168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128}, + { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 } + }, + { + { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, + {141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128}, + { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 } + }, + { + { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + {244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}, + {238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128} + } + } +}; + +RK_S32 const default_prob_mv_tbl[2][19] = { + { + 162, 128, 225, 146, 172, 147, 214, 39, 156, 128, + 129, 132, 75, 145, 178, 206, 239, 254, 254 + }, + + { + 164, 128, 204, 170, 119, 235, 140, 230, 228, 128, + 130, 130, 74, 148, 180, 203, 236, 254, 254 + } +}; + +RK_S32 const vp8_prob_cost_tbl[] = { + 2048, 2048, 1792, 1642, 1536, 1454, 1386, 1329, 1280, 1236, + 1198, 1162, 1130, 1101, 1073, 1048, 1024, 1002, 980, 961, + 942, 924, 906, 890, 874, 859, 845, 831, 817, 804, + 792, 780, 768, 757, 746, 735, 724, 714, 705, 695, + 686, 676, 668, 659, 650, 642, 634, 626, 618, 611, + 603, 596, 589, 582, 575, 568, 561, 555, 548, 542, + 536, 530, 524, 518, 512, 506, 501, 495, 490, 484, + 479, 474, 468, 463, 458, 453, 449, 444, 439, 434, + 430, 425, 420, 416, 412, 407, 403, 399, 394, 390, + 386, 382, 378, 374, 370, 366, 362, 358, 355, 351, + 347, 343, 340, 336, 333, 329, 326, 322, 319, 315, + 312, 309, 305, 302, 299, 296, 292, 289, 286, 283, + 280, 277, 274, 271, 268, 265, 262, 259, 256, 253, + 250, 247, 245, 242, 239, 236, 234, 231, 228, 226, + 223, 220, 218, 215, 212, 210, 207, 205, 202, 200, + 197, 195, 193, 190, 188, 185, 183, 181, 178, 176, + 174, 171, 169, 167, 164, 162, 160, 158, 156, 153, + 151, 149, 147, 145, 143, 140, 138, 136, 134, 132, + 130, 128, 126, 124, 122, 120, 118, 116, 114, 112, + 110, 108, 106, 104, 102, 101, 99, 97, 95, 93, + 91, 89, 87, 86, 84, 82, 80, 78, 77, 75, + 73, 71, 70, 68, 66, 64, 63, 61, 59, 58, + 56, 54, 53, 51, 49, 48, 46, 44, 43, 41, + 40, 38, 36, 35, 33, 32, 30, 28, 27, 25, + 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, + 9, 7, 6, 4, 3, 1 +}; + +RK_S32 const coeff_update_prob_tbl[4][8][3][11] = { + { + { + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255}, + {249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255}, + {234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255}, + {250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255}, + {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + } + }, + { + { + {217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255}, + {234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255} + }, + { + {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255}, + {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + } + }, + + { + { + {186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255}, + {234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255}, + {251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255} + }, + { + {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255} + }, + { + {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + } + }, + + { + { + {248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255}, + {248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255}, + {246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255}, + {252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255} + }, + { + {255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255}, + {248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255}, + {253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255}, + {252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255}, + {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + }, + { + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} + } + } +}; + +RK_S32 const mv_update_prob_tbl[2][19] = { + { + 237, 246, 253, 253, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 250, 250, 252, 254, 254 + }, + { + 231, 243, 245, 253, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 251, 251, 254, 254, 254 + } +}; + +RK_S32 const default_skip_false_prob_tbl[128] = { + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 251, 248, 244, 240, 236, 232, 229, 225, + 221, 217, 213, 208, 204, 199, 194, 190, + 187, 183, 179, 175, 172, 168, 164, 160, + 157, 153, 149, 145, 142, 138, 134, 130, + 127, 124, 120, 117, 114, 110, 107, 104, + 101, 98, 95, 92, 89, 86, 83, 80, + 77, 74, 71, 68, 65, 62, 59, 56, + 53, 50, 47, 44, 41, 38, 35, 32, + 30, 28, 26, 24, 22, 20, 18, 16, +}; + +RK_S32 const y_mode_prob_tbl[4] = { + 112, 86, 140, 37 +}; + +RK_S32 const uv_mode_prob_tbl[3] = { + 162, 101, 204 +}; + +Vp8eTree const mv_tree_tbl[] = { + {0, 3, {0, 1, 2}}, /* mv_0 000 */ + {1, 3, {0, 1, 2}}, /* mv_1 001 */ + {2, 3, {0, 1, 3}}, /* mv_2 010 */ + {3, 3, {0, 1, 3}}, /* mv_3 011 */ + {4, 3, {0, 4, 5}}, /* mv_4 100 */ + {5, 3, {0, 4, 5}}, /* mv_5 101 */ + {6, 3, {0, 4, 6}}, /* mv_6 110 */ + {7, 3, {0, 4, 6}}, /* mv_7 111 */ +}; + +RK_S32 const dc_q_lookup_tbl[QINDEX_RANGE] = { + 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, + 13, 14, 15, 16, 17, 17, 18, 19, 20, 20, + 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 91, 93, 95, 96, + 98, 100, 101, 102, 104, 106, 108, 110, 112, 114, + 116, 118, 122, 124, 126, 128, 130, 132, 134, 136, + 138, 140, 143, 145, 148, 151, 154, 157 +}; + +RK_S32 const ac_q_lookup_tbl[QINDEX_RANGE] = { + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 60, 62, 64, 66, 68, + 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, + 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, + 110, 112, 114, 116, 119, 122, 125, 128, 131, 134, + 137, 140, 143, 146, 149, 152, 155, 158, 161, 164, + 167, 170, 173, 177, 181, 185, 189, 193, 197, 201, + 205, 209, 213, 217, 221, 225, 229, 234, 239, 245, + 249, 254, 259, 264, 269, 274, 279, 284 +}; + +RK_S32 const q_rounding_factors_tbl[QINDEX_RANGE] = { + 56, 56, 56, 56, 56, 56, 56, 56, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48 +}; + +RK_S32 const q_zbin_factors_tbl[QINDEX_RANGE] = { + 64, 64, 64, 64, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80 +}; + +RK_S32 const zbin_boost_tbl[16] = { + 0, 0, 8, 10, 12, 14, 16, 20, 24, 28, + 32, 36, 40, 44, 44, 44 +}; + +RK_S32 const vp8_split_penalty_tbl[128] = { + 24, 25, 26, 26, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 52, 53, 54, + 56, 57, 59, 60, 62, 63, 65, 67, 68, 70, 72, 74, 76, 78, 80, 82, + 84, 86, 88, 91, 93, 95, 98, 100, 103, 106, 108, 111, 114, 117, 120, 123, + 126, 130, 133, 136, 140, 144, 147, 151, 155, 159, 163, 167, 172, 176, 181, 185, + 190, 195, 200, 205, 211, 216, 222, 227, 233, 239, 245, 252, 258, 265, 272, 279, + 286, 293, 301, 309, 317, 325, 333, 342, 351, 360, 369, 379, 388, 398, 409, 419, + 430, 441, 453, 464, 476, 488, 501, 514, 527, 541, 555, 569, 584, 599, 614, 630 +}; + +RK_S32 const weight_tbl[128] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, + 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, + 14, 14, 14, 14, 15, 15, 15, 16, 16, 17, + 17, 18, 18, 19, 19, 20, 20, 20, 21, 22, + 23, 23, 24, 24, 25, 25, 26, 27, 28, 28, + 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 44, 44, 46, 47, 48, + 50, 51, 52, 54, 55, 57, 58, 61 +}; + +RK_S32 const intra4_mode_tree_penalty_tbl[] = { + 280, 622, 832, 1177, 1240, 1341, 1085, 1259, 1357, 1495 +}; + +RK_S32 const intra16_mode_tree_penalty_tbl[] = { + 305, 841, 914, 1082 +}; + +RK_S32 const inter_level_tbl[128] = { + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, + 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, + 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, + 18, 19, 19, 20, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 28, + 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 48, 49, 50, 51, 53, 54, 56, 57, 59, + 60, 62, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +RK_S32 const offset_tbl[] = { + -1, -1, -1, 0, 1, 2, -1, 3, 4, -1, 5, 6, -1, 7, 8, -1, + 9, 10, -1, 11, 12, 13, 14, 15, -1, 16, 17, -1, 18, 19, -1, 20, + 21, -1, 22, 23, -1, 24, 25, -1, 26, 27, 28, 29, 30, -1, 31, 32, + -1, 33, 34, -1, 35, 36, -1, 37, 38, -1, 39, 40, -1, 41, 42, 43, + 44, 45, -1, 46, 47, -1, 48, 49, -1, 50, 51, -1, 52, 53, -1, 54, + 55, -1, 56, 57, -1, -1, -1, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219 +}; \ No newline at end of file diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_table.h b/mpp/hal/vpu/vp8e/hal_vp8e_table.h new file mode 100644 index 00000000..8b29d13a --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_table.h @@ -0,0 +1,65 @@ +/* + * 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_VP8E_TABLE_H__ +#define __HAL_VP8E_TABLE_H__ + +#include "rk_type.h" + +#include "hal_vp8e_base.h" +#include "hal_vp8e_putbit.h" + +extern RK_S32 const default_prob_coeff_tbl[4][8][3][11]; + +extern RK_S32 const default_prob_mv_tbl[2][19]; + +extern RK_S32 const vp8_prob_cost_tbl[]; + +extern RK_S32 const coeff_update_prob_tbl[4][8][3][11]; + +extern RK_S32 const mv_update_prob_tbl[2][19]; + +extern RK_S32 const default_skip_false_prob_tbl[128]; + +extern RK_S32 const y_mode_prob_tbl[4]; + +extern RK_S32 const uv_mode_prob_tbl[3]; + +extern Vp8eTree const mv_tree_tbl[]; + +extern RK_S32 const dc_q_lookup_tbl[QINDEX_RANGE]; + +extern RK_S32 const ac_q_lookup_tbl[QINDEX_RANGE]; + +extern RK_S32 const q_rounding_factors_tbl[QINDEX_RANGE]; + +extern RK_S32 const q_zbin_factors_tbl[QINDEX_RANGE]; + +extern RK_S32 const zbin_boost_tbl[16]; + +extern RK_S32 const vp8_split_penalty_tbl[128]; + +extern RK_S32 const weight_tbl[128]; + +extern RK_S32 const intra4_mode_tree_penalty_tbl[]; + +extern RK_S32 const intra16_mode_tree_penalty_tbl[]; + +const RK_S32 const inter_level_tbl[128]; + +extern RK_S32 const offset_tbl[]; + +#endif /*__HAL_VP8E_TBL_H__*/ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_vepu1.c b/mpp/hal/vpu/vp8e/hal_vp8e_vepu1.c new file mode 100644 index 00000000..ab3f3842 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_vepu1.c @@ -0,0 +1,489 @@ +/* + * 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_vp8e_vepu1" + +#include + +#include "mpp_mem.h" +#include "mpp_rc.h" + +#include "vp8e_syntax.h" + +#include "hal_vp8e_base.h" +#include "hal_vp8e_vepu1.h" +#include "hal_vp8e_vepu1_reg.h" +#include "hal_vp8e_debug.h" + +#define SWREG_AMOUNT_VEPU1 (164) +#define HW_STATUS_MASK 0x58 +#define HW_STATUS_BUFFER_FULL 0x20 +#define HW_STATUS_FRAME_READY 0x04 + +static MPP_RET vp8e_vpu_frame_start(void *hal) +{ + RK_S32 i = 0; + HalVp8eCtx *ctx = (HalVp8eCtx *) hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + Vp8eVepu1Reg_t *regs = (Vp8eVepu1Reg_t *) ctx->regs; + + memset(regs, 0, sizeof(Vp8eVepu1Reg_t)); + + regs->sw1.val = hw_cfg->irq_disable ? (regs->sw1.val | 0x02) : + (regs->sw1.val & 0xfffffffd); + + + if (hw_cfg->input_format < INPUT_RGB565) + regs->sw2.val = 0xd00f; + + else if (hw_cfg->input_format < INPUT_RGB888) + regs->sw2.val = 0xd00e; + else + regs->sw2.val = 0x900e; + + regs->sw5.base_stream = hw_cfg->output_strm_base; + + regs->sw6.base_control = hw_cfg->size_tbl_base; + regs->sw14.nal_size_write = (hw_cfg->size_tbl_base != 0); + regs->sw14.mv_write = (hw_cfg->mv_output_base != 0); + + regs->sw7.base_ref_lum = hw_cfg->internal_img_lum_base_r[0]; + regs->sw8.base_ref_chr = hw_cfg->internal_img_chr_base_r[0]; + regs->sw9.base_rec_lum = hw_cfg->internal_img_lum_base_w; + regs->sw10.base_rec_chr = hw_cfg->internal_img_chr_base_w; + + regs->sw11.base_in_lum = hw_cfg->input_lum_base; + regs->sw12.base_in_cb = hw_cfg->input_cb_base; + regs->sw13.base_in_cr = hw_cfg->input_cr_base; + + regs->sw14.int_timeout = 1; + regs->sw14.int_slice_ready = hw_cfg->int_slice_ready; + regs->sw14.rec_write_disable = hw_cfg->rec_write_disable; + regs->sw14.width = hw_cfg->mbs_in_row; + regs->sw14.height = hw_cfg->mbs_in_col; + regs->sw14.picture_type = hw_cfg->frame_coding_type; + regs->sw14.encoding_mode = hw_cfg->coding_type; + + regs->sw15.chr_offset = hw_cfg->input_chroma_base_offset; + regs->sw15.lum_offset = hw_cfg->input_luma_base_offset; + regs->sw15.row_length = hw_cfg->pixels_on_row; + regs->sw15.x_fill = hw_cfg->x_fill; + regs->sw15.y_fill = hw_cfg->y_fill; + regs->sw15.input_format = hw_cfg->input_format; + regs->sw15.input_rot = hw_cfg->input_rotation; + + regs->sw18.cabac_enable = hw_cfg->enable_cabac; + regs->sw18.ip_intra16_favor = hw_cfg->intra_16_favor; + regs->sw21.inter_favor = hw_cfg->inter_favor; + regs->sw18.disable_qp_mv = hw_cfg->disable_qp_mv; + regs->sw18.deblocking = hw_cfg->filter_disable; + regs->sw21.skip_penalty = hw_cfg->skip_penalty; + regs->sw19.split_mv = hw_cfg->split_mv_mode; + regs->sw20.split_penalty_16x8 = hw_cfg->split_penalty[0]; + regs->sw20.split_penalty_8x8 = hw_cfg->split_penalty[1]; + regs->sw20.split_penalty_8x4 = hw_cfg->split_penalty[2]; + regs->sw62.split_penalty4x4 = hw_cfg->split_penalty[3]; + regs->sw62.zero_mv_favor = hw_cfg->zero_mv_favor; + + regs->sw22.strm_hdr_rem1 = hw_cfg->strm_start_msb; + regs->sw23.strm_hdr_rem2 = hw_cfg->strm_start_lsb; + regs->sw24.strm_buf_limit = hw_cfg->output_strm_size; + + regs->sw16.base_ref_lum2 = hw_cfg->internal_img_lum_base_r[1]; + regs->sw17.base_ref_chr2 = hw_cfg->internal_img_chr_base_r[1]; + + regs->sw27.y1_quant_dc = hw_cfg->y1_quant_dc[0]; + regs->sw28.y1_quant_ac = hw_cfg->y1_quant_ac[0]; + regs->sw29.y2_quant_dc = hw_cfg->y2_quant_dc[0]; + regs->sw30.y2_quant_ac = hw_cfg->y2_quant_ac[0]; + regs->sw31.ch_quant_dc = hw_cfg->ch_quant_dc[0]; + regs->sw32.ch_quant_ac = hw_cfg->ch_quant_ac[0]; + + regs->sw27.y1_zbin_dc = hw_cfg->y1_zbin_dc[0]; + regs->sw28.y1_zbin_ac = hw_cfg->y1_zbin_ac[0]; + regs->sw29.y2_zbin_dc = hw_cfg->y2_zbin_dc[0]; + regs->sw30.y2_zbin_ac = hw_cfg->y2_zbin_ac[0]; + regs->sw31.ch_zbin_dc = hw_cfg->ch_zbin_dc[0]; + regs->sw32.ch_zbin_ac = hw_cfg->ch_zbin_ac[0]; + + regs->sw27.y1_round_dc = hw_cfg->y1_round_dc[0]; + regs->sw28.y1_round_ac = hw_cfg->y1_round_ac[0]; + regs->sw29.y2_round_dc = hw_cfg->y2_round_dc[0]; + regs->sw30.y2_round_ac = hw_cfg->y2_round_ac[0]; + regs->sw31.ch_round_dc = hw_cfg->ch_round_dc[0]; + regs->sw32.ch_round_ac = hw_cfg->ch_round_ac[0]; + + regs->sw33.y1_dequant_dc = hw_cfg->y1_dequant_dc[0]; + regs->sw33.y1_dequant_ac = hw_cfg->y1_dequant_ac[0]; + regs->sw33.y2_dequant_dc = hw_cfg->y2_dequant_dc[0]; + regs->sw34.y2_dequant_ac = hw_cfg->y2_dequant_ac[0]; + regs->sw34.ch_dequant_dc = hw_cfg->ch_dequant_dc[0]; + regs->sw34.ch_dequant_ac = hw_cfg->ch_dequant_ac[0]; + + regs->sw33.mv_ref_idx = hw_cfg->mv_ref_idx[0]; + regs->sw34.mv_ref_idx2 = hw_cfg->mv_ref_idx[1]; + regs->sw34.ref2_enable = hw_cfg->ref2_enable; + + regs->sw35.bool_enc_value = hw_cfg->bool_enc_value; + regs->sw36.bool_enc_value_bits = hw_cfg->bool_enc_value_bits; + regs->sw36.bool_enc_range = hw_cfg->bool_enc_range; + + regs->sw36.filter_level = hw_cfg->filter_level[0]; + regs->sw36.golden_penalty = hw_cfg->golden_penalty; + regs->sw36.filter_sharpness = hw_cfg->filter_sharpness; + regs->sw36.dct_partition_count = hw_cfg->dct_partitions; + + regs->sw37.start_offset = hw_cfg->first_free_bit; + + regs->sw39.base_next_lum = hw_cfg->vs_next_luma_base; + regs->sw40.stab_mode = hw_cfg->vs_mode; + + regs->sw19.dmv_penalty4p = hw_cfg->diff_mv_penalty[0]; + regs->sw19.dmv_penalty1p = hw_cfg->diff_mv_penalty[1]; + regs->sw19.dmv_penaltyqp = hw_cfg->diff_mv_penalty[2]; + + regs->sw51.base_cabac_ctx = hw_cfg->cabac_tbl_base; + regs->sw52.base_mv_write = hw_cfg->mv_output_base; + + regs->sw53.rgb_coeff_a = hw_cfg->rgb_coeff_a; + regs->sw53.rgb_coeff_b = hw_cfg->rgb_coeff_b; + regs->sw54.rgb_coeff_c = hw_cfg->rgb_coeff_a; + regs->sw54.rgb_coeff_e = hw_cfg->rgb_coeff_e; + regs->sw55.rgb_coeff_f = hw_cfg->rgb_coeff_f; + + regs->sw55.r_mask_msb = hw_cfg->r_mask_msb; + regs->sw55.g_mask_msb = hw_cfg->g_mask_msb; + regs->sw55.b_mask_msb = hw_cfg->b_mask_msb; + + regs->sw57.cir_start = hw_cfg->cir_start; + regs->sw57.cir_interval = hw_cfg->cir_interval; + + regs->sw56.intra_area_left = hw_cfg->intra_area_left; + regs->sw56.intra_area_right = hw_cfg->intra_area_right; + regs->sw56.intra_area_top = hw_cfg->intra_area_top; + regs->sw56.intra_area_bottom = hw_cfg->intra_area_bottom; + regs->sw60.roi1_left = hw_cfg->roi1_left; + regs->sw60.roi1_right = hw_cfg->roi1_right; + regs->sw60.roi1_top = hw_cfg->roi1_top; + regs->sw60.roi1_bottom = hw_cfg->roi1_bottom; + + regs->sw61.roi2_left = hw_cfg->roi2_left; + regs->sw61.roi2_right = hw_cfg->roi2_right; + regs->sw61.roi2_top = hw_cfg->roi2_top; + regs->sw61.roi2_bottom = hw_cfg->roi2_bottom; + + regs->sw58.base_partition1 = hw_cfg->partition_Base[0]; + regs->sw59.base_partition2 = hw_cfg->partition_Base[1]; + regs->sw26.base_prob_count = hw_cfg->prob_count_base; + + regs->sw64.mode0_penalty = hw_cfg->intra_mode_penalty[0]; + regs->sw64.mode1_penalty = hw_cfg->intra_mode_penalty[1]; + regs->sw65.mode2_penalty = hw_cfg->intra_mode_penalty[2]; + regs->sw65.mode3_penalty = hw_cfg->intra_mode_penalty[3]; + + for (i = 0; i < 5; i++) { + regs->sw66_70[i].b_mode_0_penalty = hw_cfg->intra_b_mode_penalty[2 * i]; + regs->sw66_70[i].b_mode_1_penalty = hw_cfg->intra_b_mode_penalty[2 * i + 1]; + } + + regs->sw34.segment_enable = hw_cfg->segment_enable; + regs->sw34.segment_map_update = hw_cfg->segment_map_update; + regs->sw71.base_segment_map = hw_cfg->segment_map_base; + + for (i = 0; i < 3; i++) { + regs->sw72_95[0 + i * 8].num_0.y1_quant_dc = hw_cfg->y1_quant_dc[1 + i]; + regs->sw72_95[0 + i * 8].num_0.y1_zbin_dc = hw_cfg->y1_zbin_dc[1 + i]; + regs->sw72_95[0 + i * 8].num_0.y1_round_dc = hw_cfg->y1_round_dc[1 + i]; + + regs->sw72_95[1 + i * 8].num_1.y1_quant_ac = hw_cfg->y1_quant_ac[1 + i]; + regs->sw72_95[1 + i * 8].num_1.y1_zbin_ac = hw_cfg->y1_zbin_ac[1 + i]; + regs->sw72_95[1 + i * 8].num_1.y1_round_ac = hw_cfg->y1_round_ac[1 + i]; + + regs->sw72_95[2 + i * 8].num_2.y2_quant_dc = hw_cfg->y2_quant_dc[1 + i]; + regs->sw72_95[2 + i * 8].num_2.y2_zbin_dc = hw_cfg->y2_zbin_dc[1 + i]; + regs->sw72_95[2 + i * 8].num_2.y2_round_dc = hw_cfg->y2_round_dc[1 + i]; + + regs->sw72_95[3 + i * 8].num_3.y2_quant_ac = hw_cfg->y2_quant_ac[1 + i]; + regs->sw72_95[3 + i * 8].num_3.y2_zbin_ac = hw_cfg->y2_zbin_ac[1 + i]; + regs->sw72_95[3 + i * 8].num_3.y2_round_ac = hw_cfg->y2_round_ac[1 + i]; + + regs->sw72_95[4 + i * 8].num_4.ch_quant_dc = hw_cfg->ch_quant_dc[1 + i]; + regs->sw72_95[4 + i * 8].num_4.ch_zbin_dc = hw_cfg->ch_zbin_dc[1 + i]; + regs->sw72_95[4 + i * 8].num_4.ch_round_dc = hw_cfg->ch_round_dc[1 + i]; + + regs->sw72_95[5 + i * 8].num_5.ch_quant_ac = hw_cfg->ch_quant_ac[1 + i]; + regs->sw72_95[5 + i * 8].num_5.ch_zbin_ac = hw_cfg->ch_zbin_ac[1 + i]; + regs->sw72_95[5 + i * 8].num_5.ch_round_ac = hw_cfg->ch_round_ac[1 + i]; + + regs->sw72_95[6 + i * 8].num_6.y1_dequant_dc = hw_cfg->y1_dequant_dc[1 + i]; + regs->sw72_95[6 + i * 8].num_6.y1_dequant_ac = hw_cfg->y1_dequant_ac[1 + i]; + regs->sw72_95[6 + i * 8].num_6.y2_dequant_dc = hw_cfg->y2_dequant_dc[1 + i]; + + regs->sw72_95[7 + i * 8].num_7.y2_dequant_ac = hw_cfg->y2_dequant_ac[1 + i]; + regs->sw72_95[7 + i * 8].num_7.ch_dequant_dc = hw_cfg->ch_dequant_dc[1 + i]; + regs->sw72_95[7 + i * 8].num_7.ch_dequant_ac = hw_cfg->ch_dequant_ac[1 + i]; + regs->sw72_95[7 + i * 8].num_7.filter_level = hw_cfg->filter_level[1 + i]; + + } + + regs->sw162.lf_ref_delta0 = hw_cfg->lf_ref_delta[0] & mask_7b; + regs->sw162.lf_ref_delta1 = hw_cfg->lf_ref_delta[1] & mask_7b; + regs->sw162.lf_ref_delta2 = hw_cfg->lf_ref_delta[2] & mask_7b; + regs->sw162.lf_ref_delta3 = hw_cfg->lf_ref_delta[3] & mask_7b; + regs->sw163.lf_mode_delta0 = hw_cfg->lf_mode_delta[0] & mask_7b; + regs->sw163.lf_mode_delta1 = hw_cfg->lf_mode_delta[1] & mask_7b; + regs->sw163.lf_mode_delta2 = hw_cfg->lf_mode_delta[2] & mask_7b; + regs->sw163.lf_mode_delta3 = hw_cfg->lf_mode_delta[3] & mask_7b; + + RK_S32 j = 0; + + for (j = 0; j < 32; j++) { + regs->sw96_127[j].penalty_0 = hw_cfg->dmv_penalty[j * 4 + 3]; + regs->sw96_127[j].penalty_1 = hw_cfg->dmv_penalty[j * 4 + 2]; + regs->sw96_127[j].penalty_2 = hw_cfg->dmv_penalty[j * 4 + 1]; + regs->sw96_127[j].penalty_3 = hw_cfg->dmv_penalty[j * 4]; + + regs->sw128_159[j].qpel_penalty_0 = hw_cfg->dmv_qpel_penalty[j * 4 + 3]; + regs->sw128_159[j].qpel_penalty_1 = hw_cfg->dmv_qpel_penalty[j * 4 + 2]; + regs->sw128_159[j].qpel_penalty_2 = hw_cfg->dmv_qpel_penalty[j * 4 + 1]; + regs->sw128_159[j].qpel_penalty_3 = hw_cfg->dmv_qpel_penalty[j * 4]; + } + + regs->sw14.enable = 1; + + return MPP_OK; +} + +MPP_RET hal_vp8e_vepu1_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + + ctx->cfg = cfg->cfg; + ctx->set = cfg->set; + + ctx->int_cb = cfg->hal_int_cb; + + ctx->buffers = mpp_calloc(Vp8eVpuBuf, 1); + if (ctx->buffers == NULL) { + mpp_err("failed to malloc buffers"); + return MPP_ERR_NOMEM; + } + ctx->buffer_ready = 0; + ctx->frame_cnt = 0; + ctx->gop_len = 0; + ctx->frame_type = VP8E_FRM_KEY; + ctx->prev_frame_lost = 0; + ctx->frame_size = 0; + ctx->reg_size = SWREG_AMOUNT_VEPU1; + + hw_cfg->irq_disable = 0; + + hw_cfg->rounding_ctrl = 0; + hw_cfg->cp_distance_mbs = 0; + hw_cfg->recon_img_id = 0; + hw_cfg->input_lum_base = 0; + hw_cfg->input_cb_base = 0; + hw_cfg->input_cr_base = 0; + + hal_vp8e_init_qp_table(hal); + + MppDevCfg dev_cfg = { + .type = MPP_CTX_ENC, /* type */ + .coding = MPP_VIDEO_CodingVP8, /* 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); + return ret; + } else { + vp8e_hal_dbg(VP8E_DBG_HAL_FUNCTION, "mpp_device_init success.\n"); + return ret; + } +} + +MPP_RET hal_vp8e_vepu1_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + hal_vp8e_buf_free(ctx); + + ret = mpp_device_deinit(&ctx->dev_ctx); + + if (ret) { + mpp_err("mpp_device_deinit failed ret: %d\n", ret); + } else { + vp8e_hal_dbg(VP8E_DBG_HAL_FUNCTION, "mpp_device_deinit success.\n"); + } + + MPP_FREE(ctx->regs); + MPP_FREE(ctx->buffers); + + return ret; +} + +MPP_RET hal_vp8e_vepu1_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + if (!ctx->buffer_ready) { + ret = hal_vp8e_setup(hal); + if (ret) { + hal_vp8e_vepu1_deinit(hal); + mpp_err("failed to init hal vp8e\n"); + } else { + ctx->buffer_ready = 1; + } + } + + memset(ctx->stream_size, 0, sizeof(ctx->stream_size)); + + hal_vp8e_enc_strm_code(ctx, task); + vp8e_vpu_frame_start(ctx); + + return MPP_OK; +} + +MPP_RET hal_vp8e_vepu1_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + ret = mpp_device_send_reg(ctx->dev_ctx, (RK_U32 *)ctx->regs, ctx->reg_size); + if (ret) { + mpp_err("failed to send regs to kernel!!!\n"); + } else { + vp8e_hal_dbg(VP8E_DBG_HAL_FUNCTION, "mpp_device_send_reg success.\n"); + } + + if (VP8E_DBG_HAL_DUMP_REG & vp8e_hal_debug) { + RK_U32 i = 0; + RK_U32 *tmp = (RK_U32 *)ctx->regs; + + for (; i < ctx->reg_size; i++) + mpp_log("reg[%d]:%x\n", i, tmp[i]); + } + + (void)task; + return ret; +} + +static void vp8e_update_hw_cfg(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + Vp8eVepu1Reg_t * regs = (Vp8eVepu1Reg_t *)ctx->regs; + + hw_cfg->output_strm_base = regs->sw24.strm_buf_limit / 8; + hw_cfg->qp_sum = regs->sw25.qp_sum * 2; + hw_cfg->mad_count = regs->sw38.mad_count; + hw_cfg->rlc_count = regs->sw37.rlc_sum * 4; + + hw_cfg->intra_16_favor = -1; + hw_cfg->inter_favor = -1; + hw_cfg->diff_mv_penalty[0] = -1; + hw_cfg->diff_mv_penalty[1] = -1; + hw_cfg->diff_mv_penalty[2] = -1; + hw_cfg->skip_penalty = -1; + hw_cfg->golden_penalty = -1; + hw_cfg->split_penalty[0] = -1; + hw_cfg->split_penalty[1] = -1; + hw_cfg->split_penalty[3] = -1; + +} + +MPP_RET hal_vp8e_vepu1_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eFeedback *fb = &ctx->feedback; + IOInterruptCB int_cb = ctx->int_cb; + Vp8eVepu1Reg_t *regs = (Vp8eVepu1Reg_t *)ctx->regs; + + if (NULL == ctx->dev_ctx) { + mpp_err_f("invalid dev ctx\n"); + return MPP_NOK; + } + + ret = mpp_device_wait_reg(ctx->dev_ctx, (RK_U32 *)ctx->regs, ctx->reg_size); + if (ret != MPP_OK) { + mpp_err("hardware returns error: %d\n", ret); + return ret; + } else { + vp8e_hal_dbg(VP8E_DBG_HAL_FUNCTION, "mpp_device_wait_reg success.\n"); + } + + fb->hw_status = regs->sw1.val & HW_STATUS_MASK; + if (regs->sw1.val & HW_STATUS_FRAME_READY) + vp8e_update_hw_cfg(ctx); + else if (regs->sw1.val & HW_STATUS_BUFFER_FULL) + ctx->bitbuf[1].size = 0; + + hal_vp8e_update_buffers(ctx, task); + + RcHalResult result; + ctx->frame_cnt++; + if (ctx->frame_cnt % ctx->gop_len == 0) { + ctx->frame_type = VP8E_FRM_KEY; + result.type = INTRA_FRAME; + } else { + ctx->frame_type = VP8E_FRM_P; + result.type = INTER_P_FRAME; + } + + result.bits = ctx->frame_size * 8; + + if (int_cb.callBack) { + fb->result = &result; + int_cb.callBack(int_cb.opaque, fb); + } + + return ret; +} + +MPP_RET hal_vp8e_vepu1_reset(void *hal) +{ + vp8e_hal_enter(); + + vp8e_hal_leave(); + (void)hal; + return MPP_OK; +} + +MPP_RET hal_vp8e_vepu1_flush(void *hal) +{ + vp8e_hal_enter(); + + vp8e_hal_leave(); + (void)hal; + return MPP_OK; +} + +MPP_RET hal_vp8e_vepu1_control(void *hal, RK_S32 cmd, void *param) +{ + (void)hal; + (void)cmd; + (void)param; + + return MPP_OK; +} diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_vepu1.h b/mpp/hal/vpu/vp8e/hal_vp8e_vepu1.h new file mode 100644 index 00000000..de18f7aa --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_vepu1.h @@ -0,0 +1,37 @@ +/* + * 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_VP8E_VEPU1_H__ +#define __HAL_VP8E_VEPU1_H__ + +#include "hal_vp8e_base.h" + +#ifdef __cplusplus +extern "C" { +#endif +MPP_RET hal_vp8e_vepu1_init(void *hal, MppHalCfg *cfg); +MPP_RET hal_vp8e_vepu1_deinit(void *hal); +MPP_RET hal_vp8e_vepu1_gen_regs(void *hal, HalTaskInfo *task); +MPP_RET hal_vp8e_vepu1_start(void *hal, HalTaskInfo *task); +MPP_RET hal_vp8e_vepu1_wait(void *hal, HalTaskInfo *task); +MPP_RET hal_vp8e_vepu1_reset(void *hal); +MPP_RET hal_vp8e_vepu1_flush(void *hal); +MPP_RET hal_vp8e_vepu1_control(void *hal, RK_S32 cmd, void *param); +#ifdef __cplusplus +} +#endif + +#endif /*__HAL_VP8E_VEPU1_H__*/ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_vepu1_reg.h b/mpp/hal/vpu/vp8e/hal_vp8e_vepu1_reg.h new file mode 100644 index 00000000..8d34aebd --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_vepu1_reg.h @@ -0,0 +1,455 @@ +/* + * 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_VP8E_VEPU1_REG_H__ +#define __HAL_VP8E_VEPU1_REG_H__ + +#include "rk_type.h" + +typedef struct { + RK_U32 sw0; + + struct { + RK_U32 val : 32; + } sw1; + + struct { + RK_U32 val : 32; + } sw2; + + RK_U32 sw3_4[2]; + + struct { + RK_U32 base_stream : 32; + } sw5; + + struct { + RK_U32 base_control : 32; + } sw6; + + struct { + RK_U32 base_ref_lum : 32; + } sw7; + + struct { + RK_U32 base_ref_chr : 32; + } sw8; + + struct { + RK_U32 base_rec_lum : 32; + } sw9; + + struct { + RK_U32 base_rec_chr : 32; + } sw10; + + struct { + RK_U32 base_in_lum : 32; + } sw11; + + struct { + RK_U32 base_in_cb : 32; + } sw12; + + struct { + RK_U32 base_in_cr : 32; + } sw13; + + struct { + RK_U32 enable : 1; + RK_U32 encoding_mode : 2; + RK_U32 picture_type : 2; + RK_U32 : 1; + RK_U32 rec_write_disable : 1; + RK_U32 : 3; + RK_U32 height : 9; + RK_U32 width : 9; + RK_U32 int_slice_ready : 1; + RK_U32 nal_size_write : 1; + RK_U32 mv_write : 1; + RK_U32 int_timeout : 1; + } sw14; + + struct { + RK_U32 input_rot : 2; + RK_U32 input_format : 4; + RK_U32 y_fill : 4; + RK_U32 x_fill : 2; + RK_U32 row_length : 14; + RK_U32 lum_offset : 3; + RK_U32 chr_offset : 3; + } sw15; + + struct { + RK_U32 base_ref_lum2 : 32; + } sw16; + + struct { + RK_U32 base_ref_chr2 : 32; + } sw17; + + struct { + RK_U32 ip_intra16_favor : 16; + RK_U32 stream_mode : 1; + RK_U32 inter_4_restrict : 1; + RK_U32 cabac_enable : 1; + RK_U32 cabac_initidc : 2; + RK_U32 transform_8x8 : 1; + RK_U32 disable_qp_mv : 1; + RK_U32 slice_size : 7; + RK_U32 deblocking : 2; + } sw18; + + struct { + RK_U32 dmv_penalty1p : 10; + RK_U32 dmv_penalty4p : 10; + RK_U32 dmv_penaltyqp : 10; + RK_U32 split_mv : 1; + RK_U32 : 1; + } sw19; + + struct { + RK_U32 split_penalty_8x4 : 10; + RK_U32 split_penalty_8x8 : 10; + RK_U32 split_penalty_16x8 : 10; + RK_U32 : 2; + } sw20; + + struct { + RK_U32 inter_favor : 16; + RK_U32 num_slices_ready : 8; + RK_U32 skip_penalty : 8; + } sw21; + + struct { + RK_U32 strm_hdr_rem1 : 32; + } sw22; + + struct { + RK_U32 strm_hdr_rem2 : 32; + } sw23; + + struct { + RK_U32 strm_buf_limit : 32; + } sw24; + + struct { + RK_U32 qp_sum : 21; + RK_U32 : 1; + RK_U32 mad_threshold : 6; + RK_U32 mad_qp_delta : 4; + } sw25; + + struct { + RK_U32 base_prob_count : 32; + } sw26; + + struct { + RK_U32 y1_quant_dc : 14; + RK_U32 y1_zbin_dc : 9; + RK_U32 y1_round_dc : 8; + RK_U32 : 1; + } sw27; + + struct { + RK_U32 y1_quant_ac : 14; + RK_U32 y1_zbin_ac : 9; + RK_U32 y1_round_ac : 8; + RK_U32 : 1; + } sw28; + + struct { + RK_U32 y2_quant_dc : 14; + RK_U32 y2_zbin_dc : 9; + RK_U32 y2_round_dc : 8; + RK_U32 : 1; + } sw29; + + struct { + RK_U32 y2_quant_ac : 14; + RK_U32 y2_zbin_ac : 9; + RK_U32 y2_round_ac : 8; + RK_U32 : 1; + } sw30; + + struct { + RK_U32 ch_quant_dc : 14; + RK_U32 ch_zbin_dc : 9; + RK_U32 ch_round_dc : 8; + RK_U32 : 1; + } sw31; + + struct { + RK_U32 ch_quant_ac : 14; + RK_U32 ch_zbin_ac : 9; + RK_U32 ch_round_ac : 8; + RK_U32 : 1; + } sw32; + + struct { + RK_U32 y1_dequant_dc : 8; + RK_U32 y1_dequant_ac : 9; + RK_U32 y2_dequant_dc : 9; + RK_U32 mv_ref_idx : 2; + RK_U32 : 4; + } sw33; + + struct { + RK_U32 y2_dequant_ac : 9; + RK_U32 ch_dequant_dc : 8; + RK_U32 ch_dequant_ac : 9; + RK_U32 mv_ref_idx2 : 2; + RK_U32 ref2_enable : 1; + RK_U32 segment_enable : 1; + RK_U32 segment_map_update : 1; + RK_U32 : 1; + } sw34; + + struct { + RK_U32 bool_enc_value : 32; + } sw35; + + struct { + RK_U32 bool_enc_range : 8; + RK_U32 bool_enc_value_bits : 5; + RK_U32 dct_partition_count : 2; + RK_U32 filter_level : 6; + RK_U32 filter_sharpness : 3; + RK_U32 golden_penalty : 8; + } sw36; + + struct { + RK_U32 rlc_sum : 23; + RK_U32 start_offset : 6; + RK_U32 : 3; + } sw37; + + struct { + RK_U32 mb_count : 16; + RK_U32 mad_count : 16; + } sw38; + + struct { + RK_U32 base_next_lum : 32; + } sw39; + + struct { + RK_U32 stab_minimum : 24; + RK_U32 : 6; + RK_U32 stab_mode : 2; + } sw40; + RK_U32 sw41_50[10]; + + struct { + RK_U32 base_cabac_ctx : 32; + } sw51; + + struct { + RK_U32 base_mv_write : 32; + } sw52; + + struct { + RK_U32 rgb_coeff_a : 16; + RK_U32 rgb_coeff_b : 16; + } sw53; + + struct { + RK_U32 rgb_coeff_c : 16; + RK_U32 rgb_coeff_e : 16; + } sw54; + + struct { + RK_U32 rgb_coeff_f : 16; + RK_U32 r_mask_msb : 5; + RK_U32 g_mask_msb : 5; + RK_U32 b_mask_msb : 5; + RK_U32 : 1; + } sw55; + + struct { + RK_U32 intra_area_bottom : 8; + RK_U32 intra_area_top : 8; + RK_U32 intra_area_right : 8; + RK_U32 intra_area_left : 8; + } sw56; + + struct { + RK_U32 cir_interval : 16; + RK_U32 cir_start : 16; + } sw57; + + struct { + RK_U32 base_partition1 : 32; + } sw58; + + struct { + RK_U32 base_partition2 : 32; + } sw59; + + struct { + RK_U32 roi1_bottom : 8; + RK_U32 roi1_top : 8; + RK_U32 roi1_right : 8; + RK_U32 roi1_left : 8; + } sw60; + + struct { + RK_U32 roi2_bottom : 8; + RK_U32 roi2_top : 8; + RK_U32 roi2_right : 8; + RK_U32 roi2_left : 8; + } sw61; + + struct { + RK_U32 roi2_delta_qp : 4; + RK_U32 roi1_delta_qp : 4; + RK_U32 mvc_inter_view_flag : 1; + RK_U32 mvc_anchor_pic_flag : 1; + RK_U32 mvc_temporal_id : 3; + RK_U32 mvc_view_id : 3; + RK_U32 mvc_priority_id : 3; + RK_U32 split_penalty4x4 : 9; + RK_U32 zero_mv_favor : 4; + } sw62; + + RK_U32 sw63; + + struct { + RK_U32 mode0_penalty : 12; + RK_U32 mode1_penalty : 12; + RK_U32 : 8; + } sw64; + + struct { + RK_U32 mode2_penalty : 12; + RK_U32 mode3_penalty : 12; + RK_U32 : 8; + } sw65; + + struct { + RK_U32 b_mode_0_penalty : 12; + RK_U32 b_mode_1_penalty : 12; + RK_U32 : 8; + } sw66_70[5]; + + struct { + RK_U32 base_segment_map : 32; + } sw71; + + union { + struct { + RK_U32 y1_quant_dc : 14; + RK_U32 y1_zbin_dc : 9; + RK_U32 y1_round_dc : 8; + RK_U32 : 1; + } num_0; + + struct { + RK_U32 y1_quant_ac : 14; + RK_U32 y1_zbin_ac : 9; + RK_U32 y1_round_ac : 8; + RK_U32 : 1; + } num_1; + + struct { + RK_U32 y2_quant_dc : 14; + RK_U32 y2_zbin_dc : 9; + RK_U32 y2_round_dc : 8; + RK_U32 : 1; + } num_2; + + struct { + RK_U32 y2_quant_ac : 14; + RK_U32 y2_zbin_ac : 9; + RK_U32 y2_round_ac : 8; + RK_U32 : 1; + } num_3; + + struct { + RK_U32 ch_quant_dc : 14; + RK_U32 ch_zbin_dc : 9; + RK_U32 ch_round_dc : 8; + RK_U32 : 1; + } num_4; + + struct { + RK_U32 ch_quant_ac : 14; + RK_U32 ch_zbin_ac : 9; + RK_U32 ch_round_ac : 8; + RK_U32 : 1; + } num_5; + + struct { + RK_U32 y1_dequant_dc : 8; + RK_U32 y1_dequant_ac : 9; + RK_U32 y2_dequant_dc : 9; + RK_U32 : 6; + } num_6; + + struct { + RK_U32 y2_dequant_ac : 9; + RK_U32 ch_dequant_dc : 8; + RK_U32 ch_dequant_ac : 9; + RK_U32 filter_level : 6; + } num_7; + + } sw72_95[24]; + + struct { + RK_U32 penalty_0 : 8; + RK_U32 penalty_1 : 8; + RK_U32 penalty_2 : 8; + RK_U32 penalty_3 : 8; + } sw96_127[32]; + + struct { + RK_U32 qpel_penalty_0 : 8; + RK_U32 qpel_penalty_1 : 8; + RK_U32 qpel_penalty_2 : 8; + RK_U32 qpel_penalty_3 : 8; + } sw128_159[32]; + + + struct { + RK_U32 cost_inter : 12; + RK_U32 dmv_cost_const : 12; + RK_U32 : 8; + } sw160; + + struct { + RK_U32 cost_golden_ref : 12; + RK_U32 : 20; + } sw161; + + struct { + RK_U32 lf_ref_delta0 : 7; //vp8_loopfilter_intra + RK_U32 lf_ref_delta1 : 7; //vp8_loopfilter_lastref + RK_U32 lf_ref_delta2 : 7; //vp8_loopfilter_glodenref + RK_U32 lf_ref_delta3 : 7; //vp8_loopfilter_alterf + RK_U32 : 4; + } sw162; + + struct { + RK_U32 lf_mode_delta0 : 7; //vp8_loopfilter_bpred + RK_U32 lf_mode_delta1 : 7; //vp8_loopfilter_zeromv + RK_U32 lf_mode_delta2 : 7; //vp8_loopfilter_newmv + RK_U32 lf_mode_delta3 : 7; //vp8_loopfilter_splitmv + RK_U32 : 4; + } sw163; + +} Vp8eVepu1Reg_t; + +#endif /*__HAL_VP8E_VEPU1_REG_H__*/ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_vepu2.c b/mpp/hal/vpu/vp8e/hal_vp8e_vepu2.c new file mode 100644 index 00000000..10185a1c --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_vepu2.c @@ -0,0 +1,486 @@ +/* + * 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_vp8e_vepu2" + +#include + +#include "mpp_mem.h" + +#include "hal_vp8e_base.h" +#include "hal_vp8e_vepu2.h" +#include "hal_vp8e_vepu2_reg.h" + +#include "mpp_rc.h" +#include "vp8e_syntax.h" +#include "hal_vp8e_debug.h" + +#define SWREG_AMOUNT_VEPU2 (184) +#define HW_STATUS_MASK 0x250 +#define HW_STATUS_BUFFER_FULL 0x20 +#define HW_STATUS_FRAME_READY 0x02 + +static MPP_RET vp8e_vpu_frame_start(void *hal) +{ + RK_S32 i; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + Vp8eVepu2Reg_t *regs = (Vp8eVepu2Reg_t *)ctx->regs; + + memset(regs, 0, sizeof(Vp8eVepu2Reg_t)); + + regs->sw109.val = hw_cfg->irq_disable ? (regs->sw109.val | 0x0100) : + (regs->sw109.val & 0xfeff); + + //((0 & (255)) << 24) | ((0 & (255)) << 16) | ((16 & (63)) << 8) | ((0 & (1)) << 2) | ((0 & (1)) << 1); + regs->sw54.val = 0x1000; + + if (hw_cfg->input_format < INPUT_RGB565) { + regs->sw105.val = 0xfc000000; + } else if (hw_cfg->input_format < INPUT_RGB888) { + regs->sw105.val = 0x7c000000; + } else { + regs->sw105.val = 0x3c000000; + } + + regs->sw77.base_stream = hw_cfg->output_strm_base; + + regs->sw78.base_control = hw_cfg->size_tbl_base; + regs->sw74.nal_size_write = hw_cfg->size_tbl_base != 0; + regs->sw109.mv_write = hw_cfg->mv_output_base != 0; + + regs->sw56.base_ref_lum = hw_cfg->internal_img_lum_base_r[0]; + regs->sw57.base_ref_chr = hw_cfg->internal_img_chr_base_r[0]; + regs->sw63.base_rec_lum = hw_cfg->internal_img_lum_base_w; + regs->sw64.base_rec_chr = hw_cfg->internal_img_chr_base_w; + + regs->sw48.base_in_lum = hw_cfg->input_lum_base; + regs->sw49.base_in_cb = hw_cfg->input_cb_base; + regs->sw50.base_in_cr = hw_cfg->input_cr_base; + +// regs->sw109.int_timeout = 1 & 1; + regs->sw109.val |= 0x0400; + regs->sw109.int_slice_ready = hw_cfg->int_slice_ready; + regs->sw109.rec_write_disable = hw_cfg->rec_write_disable; + regs->sw103.width = hw_cfg->mbs_in_row; + regs->sw103.height = hw_cfg->mbs_in_col; + regs->sw103.picture_type = hw_cfg->frame_coding_type; + regs->sw103.encoding_mode = hw_cfg->coding_type; + + regs->sw61.chr_offset = hw_cfg->input_chroma_base_offset; + regs->sw61.lum_offset = hw_cfg->input_luma_base_offset; + regs->sw61.row_length = hw_cfg->pixels_on_row; + regs->sw60.x_fill = hw_cfg->x_fill; + regs->sw60.y_fill = hw_cfg->y_fill; + regs->sw74.input_format = hw_cfg->input_format; + regs->sw74.input_rot = hw_cfg->input_rotation; + + regs->sw59.cabac_enable = hw_cfg->enable_cabac; + regs->sw75.ip_intra_16_favor = hw_cfg->intra_16_favor; + regs->sw75.inter_favor = hw_cfg->inter_favor; + regs->sw59.disable_qp_mv = hw_cfg->disable_qp_mv; + regs->sw59.deblocking = hw_cfg->filter_disable; + regs->sw60.skip_penalty = hw_cfg->skip_penalty; + regs->sw99.split_mv = hw_cfg->split_mv_mode; + regs->sw107.split_penalty_16x8 = hw_cfg->split_penalty[0]; + regs->sw107.split_penalty_8x8 = hw_cfg->split_penalty[1]; + regs->sw107.split_penalty_8x4 = hw_cfg->split_penalty[2]; + regs->sw102.split_penalty_4x4 = hw_cfg->split_penalty[3]; + regs->sw102.zero_mv_favor = hw_cfg->zero_mv_favor; + + regs->sw51.strm_hdr_rem1 = hw_cfg->strm_start_msb; + regs->sw52.strm_hdr_rem2 = hw_cfg->strm_start_lsb; + regs->sw53.strm_buf_limit = hw_cfg->output_strm_size; + + regs->sw76.base_ref_lum2 = hw_cfg->internal_img_lum_base_r[1]; + regs->sw106.base_ref_chr2 = hw_cfg->internal_img_lum_base_r[1]; + + regs->sw100.y1_quant_dc = hw_cfg->y1_quant_dc[0]; + regs->sw65.y1_quant_ac = hw_cfg->y1_quant_ac[0]; + regs->sw66.y2_quant_dc = hw_cfg->y2_quant_dc[0]; + regs->sw67.y2_quant_ac = hw_cfg->y2_quant_ac[0]; + regs->sw68.ch_quant_dc = hw_cfg->ch_quant_dc[0]; + regs->sw69.ch_quant_ac = hw_cfg->ch_quant_ac[0]; + + regs->sw100.y1_zbin_dc = hw_cfg->y1_zbin_dc[0]; + regs->sw65.y1_zbin_ac = hw_cfg->y1_zbin_ac[0]; + regs->sw66.y2_zbin_dc = hw_cfg->y2_zbin_dc[0]; + regs->sw67.y2_zbin_ac = hw_cfg->y2_zbin_ac[0]; + regs->sw68.ch_zbin_dc = hw_cfg->ch_zbin_dc[0]; + regs->sw69.ch_zbin_ac = hw_cfg->ch_zbin_ac[0]; + + regs->sw100.y1_round_dc = hw_cfg->y1_round_dc[0]; + regs->sw65.y1_round_ac = hw_cfg->y1_round_ac[0]; + regs->sw66.y2_round_dc = hw_cfg->y2_round_dc[0]; + regs->sw67.y2_round_ac = hw_cfg->y2_round_ac[0]; + regs->sw68.ch_round_dc = hw_cfg->ch_round_dc[0]; + regs->sw69.ch_round_ac = hw_cfg->ch_round_ac[0]; + + regs->sw70.y1_dequant_dc = hw_cfg->y1_dequant_dc[0]; + regs->sw70.y1_dequant_ac = hw_cfg->y1_dequant_ac[0]; + regs->sw70.y2_dequant_dc = hw_cfg->y2_dequant_dc[0]; + regs->sw71.y2_dequant_ac = hw_cfg->y2_dequant_ac[0]; + regs->sw71.ch_dequant_dc = hw_cfg->ch_dequant_dc[0]; + regs->sw71.ch_dequant_ac = hw_cfg->ch_dequant_ac[0]; + + regs->sw70.mv_ref_idx = hw_cfg->mv_ref_idx[0]; + regs->sw71.mv_ref_idx2 = hw_cfg->mv_ref_idx[1]; + regs->sw71.ref2_enable = hw_cfg->ref2_enable; + + regs->sw72.bool_enc_value = hw_cfg->bool_enc_value; + regs->sw73.bool_enc_value_bits = hw_cfg->bool_enc_value_bits; + regs->sw73.bool_enc_range = hw_cfg->bool_enc_range; + + regs->sw73.filter_level = hw_cfg->filter_level[0]; + regs->sw73.golden_penalty = hw_cfg->golden_penalty; + regs->sw73.filter_sharpness = hw_cfg->filter_sharpness; + regs->sw73.dct_partition_count = hw_cfg->dct_partitions; + + regs->sw60.start_offset = hw_cfg->first_free_bit; + + regs->sw79.base_next_lum = hw_cfg->vs_next_luma_base; + regs->sw94.stab_mode = hw_cfg->vs_mode; + + regs->sw99.dmv_penalty_4p = hw_cfg->diff_mv_penalty[0]; + regs->sw99.dmv_penalty_1p = hw_cfg->diff_mv_penalty[1]; + regs->sw99.dmv_penalty_qp = hw_cfg->diff_mv_penalty[2]; + + regs->sw81.base_cabac_ctx = hw_cfg->cabac_tbl_base; + regs->sw80.base_mv_write = hw_cfg->mv_output_base; + + regs->sw95.rgb_coeff_a = hw_cfg->rgb_coeff_a; + regs->sw95.rgb_coeff_b = hw_cfg->rgb_coeff_b; + regs->sw96.rgb_coeff_c = hw_cfg->rgb_coeff_a; + regs->sw96.rgb_coeff_e = hw_cfg->rgb_coeff_e; + regs->sw97.rgb_coeff_f = hw_cfg->rgb_coeff_f; + + regs->sw98.r_mask_msb = hw_cfg->r_mask_msb; + regs->sw98.g_mask_msb = hw_cfg->g_mask_msb; + regs->sw98.b_mask_msb = hw_cfg->b_mask_msb; + + regs->sw47.cir_start = hw_cfg->cir_start; + regs->sw47.cir_interval = hw_cfg->cir_interval; + + regs->sw46.intra_area_left = hw_cfg->intra_area_left; + regs->sw46.intra_area_right = hw_cfg->intra_area_right; + regs->sw46.intra_area_top = hw_cfg->intra_area_top; + regs->sw46.intra_area_bottom = hw_cfg->intra_area_bottom ; + regs->sw82.roi1_left = hw_cfg->roi1_left; + regs->sw82.roi1_right = hw_cfg->roi1_right; + regs->sw82.roi1_top = hw_cfg->roi1_top; + regs->sw82.roi1_bottom = hw_cfg->roi1_bottom; + + regs->sw83.roi2_left = hw_cfg->roi2_left; + regs->sw83.roi2_right = hw_cfg->roi2_right; + regs->sw83.roi2_top = hw_cfg->roi2_top; + regs->sw83.roi2_bottom = hw_cfg->roi2_bottom; + + regs->sw44.base_partition1 = hw_cfg->partition_Base[0]; + regs->sw45.base_partition2 = hw_cfg->partition_Base[1]; + regs->sw108.base_prob_count = hw_cfg->prob_count_base; + + regs->sw33.mode0_penalty = hw_cfg->intra_mode_penalty[0]; + regs->sw33.mode1_penalty = hw_cfg->intra_mode_penalty[1]; + regs->sw34.mode2_penalty = hw_cfg->intra_mode_penalty[2]; + regs->sw34.mode3_penalty = hw_cfg->intra_mode_penalty[3]; + + for (i = 0 ; i < 5; i++) { + regs->sw28_32[i].b_mode_0_penalty = hw_cfg->intra_b_mode_penalty[2 * i]; + regs->sw28_32[i].b_mode_1_penalty = hw_cfg->intra_b_mode_penalty[2 * i + 1]; + } + + regs->sw71.segment_enable = hw_cfg->segment_enable; + regs->sw71.segment_map_update = hw_cfg->segment_map_update; + regs->sw27.base_segment_map = hw_cfg->segment_map_base; + + for (i = 0; i < 3; i++) { + regs->sw0_26[0 + i * 9].num_0.y1_quant_dc = hw_cfg->y1_quant_dc[1 + i]; + regs->sw0_26[0 + i * 9].num_0.y2_quant_dc = hw_cfg->y2_quant_dc[1 + i]; + + regs->sw0_26[1 + i * 9].num_1.ch_quant_dc = hw_cfg->ch_quant_dc[1 + i]; + regs->sw0_26[1 + i * 9].num_1.y1_quant_ac = hw_cfg->y1_quant_ac[1 + i]; + + regs->sw0_26[2 + i * 9].num_2.y2_quant_ac = hw_cfg->y2_quant_ac[1 + i]; + regs->sw0_26[2 + i * 9].num_2.ch_quant_ac = hw_cfg->ch_quant_ac[1 + i]; + + regs->sw0_26[3 + i * 9].num_3.y1_zbin_dc = hw_cfg->y1_zbin_dc[1 + i]; + regs->sw0_26[3 + i * 9].num_3.y2_zbin_dc = hw_cfg->y2_zbin_dc[1 + i]; + regs->sw0_26[3 + i * 9].num_3.ch_zbin_dc = hw_cfg->ch_zbin_dc[1 + i]; + + regs->sw0_26[4 + i * 9].num_4.y1_zbin_ac = hw_cfg->y1_zbin_ac[1 + i]; + regs->sw0_26[4 + i * 9].num_4.y2_zbin_ac = hw_cfg->y2_zbin_ac[1 + i]; + regs->sw0_26[4 + i * 9].num_4.ch_zbin_ac = hw_cfg->ch_zbin_ac[1 + i]; + + regs->sw0_26[5 + i * 9].num_5.y1_round_dc = hw_cfg->y1_round_dc[1 + i]; + regs->sw0_26[5 + i * 9].num_5.y2_round_dc = hw_cfg->y2_round_dc[1 + i]; + regs->sw0_26[5 + i * 9].num_5.ch_round_dc = hw_cfg->ch_round_dc[1 + i]; + + regs->sw0_26[6 + i * 9].num_6.y1_round_ac = hw_cfg->y1_round_ac[1 + i]; + regs->sw0_26[6 + i * 9].num_6.y2_round_ac = hw_cfg->y2_round_ac[1 + i]; + regs->sw0_26[6 + i * 9].num_6.ch_round_ac = hw_cfg->ch_round_ac[1 + i]; + + regs->sw0_26[7 + i * 9].num_7.y1_dequant_dc = hw_cfg->y1_dequant_dc[1 + i]; + regs->sw0_26[7 + i * 9].num_7.y2_dequant_dc = hw_cfg->y2_dequant_dc[1 + i]; + regs->sw0_26[7 + i * 9].num_7.ch_dequant_dc = hw_cfg->ch_dequant_dc[1 + i]; + regs->sw0_26[7 + i * 9].num_7.filter_level = hw_cfg->filter_level[1 + i]; + + regs->sw0_26[8 + i * 9].num_8.y1_dequant_ac = hw_cfg->y1_dequant_ac[1 + i]; + regs->sw0_26[8 + i * 9].num_8.y2_dequant_ac = hw_cfg->y2_dequant_ac[1 + i]; + regs->sw0_26[8 + i * 9].num_8.ch_dequant_ac = hw_cfg->ch_dequant_ac[1 + i]; + } + + regs->sw40.lf_ref_delta0 = hw_cfg->lf_ref_delta[0] & mask_7b; + regs->sw42.lf_ref_delta1 = hw_cfg->lf_ref_delta[1] & mask_7b; + regs->sw42.lf_ref_delta2 = hw_cfg->lf_ref_delta[2] & mask_7b; + regs->sw42.lf_ref_delta3 = hw_cfg->lf_ref_delta[3] & mask_7b; + regs->sw40.lf_mode_delta0 = hw_cfg->lf_mode_delta[0] & mask_7b; + regs->sw43.lf_mode_delta1 = hw_cfg->lf_mode_delta[1] & mask_7b; + regs->sw43.lf_mode_delta2 = hw_cfg->lf_mode_delta[2] & mask_7b; + regs->sw43.lf_mode_delta3 = hw_cfg->lf_mode_delta[3] & mask_7b; + + RK_S32 j = 0; + for (j = 0; j < 32; j++) { + regs->sw120_183[j].penalty_0 = hw_cfg->dmv_penalty[j * 4 + 3]; + regs->sw120_183[j].penalty_1 = hw_cfg->dmv_penalty[j * 4 + 2]; + regs->sw120_183[j].penalty_2 = hw_cfg->dmv_penalty[j * 4 + 1]; + regs->sw120_183[j].penalty_3 = hw_cfg->dmv_penalty[j * 4]; + + regs->sw120_183[j + 32].penalty_0 = hw_cfg->dmv_qpel_penalty[j * 4 + 3]; + regs->sw120_183[j + 32].penalty_1 = hw_cfg->dmv_qpel_penalty[j * 4 + 2]; + regs->sw120_183[j + 32].penalty_2 = hw_cfg->dmv_qpel_penalty[j * 4 + 1]; + regs->sw120_183[j + 32].penalty_3 = hw_cfg->dmv_qpel_penalty[j * 4]; + } + + regs->sw103.enable = 0x1; + + return MPP_OK; +} + +MPP_RET hal_vp8e_vepu2_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + + ctx->cfg = cfg->cfg; + ctx->set = cfg->set; + + ctx->int_cb = cfg->hal_int_cb; + + ctx->buffers = mpp_calloc(Vp8eVpuBuf, 1); + if (ctx->buffers == NULL) { + mpp_err("failed to malloc buffers"); + return MPP_ERR_NOMEM; + } + ctx->buffer_ready = 0; + ctx->frame_cnt = 0; + ctx->gop_len = 0; + ctx->frame_type = VP8E_FRM_KEY; + ctx->prev_frame_lost = 0; + ctx->frame_size = 0; + ctx->reg_size = SWREG_AMOUNT_VEPU2; + + hw_cfg->irq_disable = 0; + + hw_cfg->rounding_ctrl = 0; + hw_cfg->cp_distance_mbs = 0; + hw_cfg->recon_img_id = 0; + hw_cfg->input_lum_base = 0; + hw_cfg->input_cb_base = 0; + hw_cfg->input_cr_base = 0; + + hal_vp8e_init_qp_table(hal); + + MppDevCfg dev_cfg = { + .type = MPP_CTX_ENC, /* type */ + .coding = MPP_VIDEO_CodingVP8, /* 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); + } else { + vp8e_hal_dbg(VP8E_DBG_HAL_FUNCTION, "mpp_device_init success.\n"); + } + return ret; +} + +MPP_RET hal_vp8e_vepu2_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + hal_vp8e_buf_free(ctx); + + ret = mpp_device_deinit(&ctx->dev_ctx); + + if (ret) { + mpp_err("mpp_device_deinit failed ret: %d\n", ret); + } else { + vp8e_hal_dbg(VP8E_DBG_HAL_FUNCTION, "mpp_device_deinit success.\n"); + } + + MPP_FREE(ctx->regs); + MPP_FREE(ctx->buffers); + + return ret; +} + +MPP_RET hal_vp8e_vepu2_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + if (!ctx->buffer_ready) { + ret = hal_vp8e_setup(hal); + if (ret) { + hal_vp8e_vepu2_deinit(hal); + mpp_err("failed to init hal vp8e\n"); + } else { + ctx->buffer_ready = 1; + } + } + + memset(ctx->stream_size, 0, sizeof(ctx->stream_size)); + + hal_vp8e_enc_strm_code(ctx, task); + vp8e_vpu_frame_start(ctx); + + return MPP_OK; +} + +MPP_RET hal_vp8e_vepu2_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + ret = mpp_device_send_reg(ctx->dev_ctx, (RK_U32 *)ctx->regs, ctx->reg_size); + if (ret) { + mpp_err("failed to send regs to kernel!!!\n"); + } else { + vp8e_hal_dbg(VP8E_DBG_HAL_FUNCTION, "mpp_device_send_reg success.\n"); + } + + if (VP8E_DBG_HAL_DUMP_REG & vp8e_hal_debug) { + RK_U32 i = 0; + RK_U32 *tmp = (RK_U32 *)ctx->regs; + + for (; i < ctx->reg_size; i++) + mpp_log("reg[%d]:%x\n", i, tmp[i]); + } + + (void)task; + return ret; +} + +static void vp8e_update_hw_cfg(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + Vp8eVepu2Reg_t *regs = (Vp8eVepu2Reg_t *) ctx->regs; + + hw_cfg->output_strm_base = regs->sw53.strm_buf_limit / 8; + hw_cfg->qp_sum = regs->sw58.qp_sum * 2; + hw_cfg->mad_count = regs->sw104.mad_count; + hw_cfg->rlc_count = regs->sw62.rlc_sum * 3; + + hw_cfg->intra_16_favor = -1; + hw_cfg->inter_favor = -1; + hw_cfg->diff_mv_penalty[0] = -1; + hw_cfg->diff_mv_penalty[1] = -1; + hw_cfg->diff_mv_penalty[2] = -1; + hw_cfg->skip_penalty = -1; + hw_cfg->golden_penalty = -1; + hw_cfg->split_penalty[0] = -1; + hw_cfg->split_penalty[1] = -1; + hw_cfg->split_penalty[3] = -1; +} + +MPP_RET hal_vp8e_vepu2_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eFeedback *fb = &ctx->feedback; + IOInterruptCB int_cb = ctx->int_cb; + Vp8eVepu2Reg_t *regs = (Vp8eVepu2Reg_t *) ctx->regs; + + if (NULL == ctx->dev_ctx) { + mpp_err_f("invalid dev ctx\n"); + return MPP_NOK; + } + + ret = mpp_device_wait_reg(ctx->dev_ctx, (RK_U32 *)ctx->regs, ctx->reg_size); + if (ret != MPP_OK) { + mpp_err("hardware returns error:%d\n", ret); + return ret; + } else { + vp8e_hal_dbg(VP8E_DBG_HAL_FUNCTION, "mpp_device_wait_reg success.\n"); + } + + fb->hw_status = regs->sw109.val & HW_STATUS_MASK; + if (regs->sw109.val & HW_STATUS_FRAME_READY) + vp8e_update_hw_cfg(ctx); + else if (regs->sw109.val & HW_STATUS_BUFFER_FULL) + ctx->bitbuf[1].size = 0; + + hal_vp8e_update_buffers(ctx, task); + + RcHalResult result; + ctx->frame_cnt++; + if (ctx->frame_cnt % ctx->gop_len == 0) { + ctx->frame_type = VP8E_FRM_KEY; + result.type = INTRA_FRAME; + } else { + ctx->frame_type = VP8E_FRM_P; + result.type = INTER_P_FRAME; + } + + result.bits = ctx->frame_size * 8; + + if (int_cb.callBack) { + fb->result = &result; + int_cb.callBack(int_cb.opaque, fb); + } + + return ret; +} + +MPP_RET hal_vp8e_vepu2_reset(void *hal) +{ + (void)hal; + + return MPP_OK; +} + +MPP_RET hal_vp8e_vepu2_flush(void *hal) +{ + (void)hal; + + return MPP_OK; +} + +MPP_RET hal_vp8e_vepu2_control(void *hal, RK_S32 cmd, void *param) +{ + (void)hal; + (void)cmd; + (void)param; + + return MPP_OK; +} diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_vepu2.h b/mpp/hal/vpu/vp8e/hal_vp8e_vepu2.h new file mode 100644 index 00000000..e26bb1e0 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_vepu2.h @@ -0,0 +1,37 @@ +/* + * 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_VP8E_VEPU2_H__ +#define __HAL_VP8E_VEPU2_H__ + +#include "hal_vp8e_base.h" + +#ifdef __cplusplus +extern "C" { +#endif +MPP_RET hal_vp8e_vepu2_init(void *hal, MppHalCfg *cfg); +MPP_RET hal_vp8e_vepu2_deinit(void *hal); +MPP_RET hal_vp8e_vepu2_gen_regs(void *hal, HalTaskInfo *task); +MPP_RET hal_vp8e_vepu2_start(void *hal, HalTaskInfo *task); +MPP_RET hal_vp8e_vepu2_wait(void *hal, HalTaskInfo *task); +MPP_RET hal_vp8e_vepu2_reset(void *hal); +MPP_RET hal_vp8e_vepu2_flush(void *hal); +MPP_RET hal_vp8e_vepu2_control(void *hal, RK_S32 cmd, void *param); +#ifdef __cplusplus +} +#endif + +#endif /*__HAL_VP8E_VEPU2_H__*/ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_vepu2_reg.h b/mpp/hal/vpu/vp8e/hal_vp8e_vepu2_reg.h new file mode 100644 index 00000000..67f55edf --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_vepu2_reg.h @@ -0,0 +1,498 @@ +/* + * 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_VP8E_VEPU2_REG_H__ +#define __HAL_VP8E_VEPU2_REG_H__ + +#include "rk_type.h" + +typedef struct { + union { + struct { + RK_U32 y1_quant_dc : 14; + RK_U32 : 2; + RK_U32 y2_quant_dc : 14; + RK_U32 : 2; + } num_0; + + struct { + RK_U32 ch_quant_dc : 14; + RK_U32 : 2; + RK_U32 y1_quant_ac : 14; + RK_U32 : 2; + } num_1; + + struct { + RK_U32 y2_quant_ac : 14; + RK_U32 : 2; + RK_U32 ch_quant_ac : 14; + RK_U32 : 2; + } num_2; + + struct { + RK_U32 y1_zbin_dc : 9; + RK_U32 y2_zbin_dc : 9; + RK_U32 ch_zbin_dc : 9; + RK_U32 : 5; + } num_3; + + struct { + RK_U32 y1_zbin_ac : 9; + RK_U32 y2_zbin_ac : 9; + RK_U32 ch_zbin_ac : 9; + RK_U32 : 5; + } num_4; + + struct { + RK_U32 y1_round_dc : 8; + RK_U32 y2_round_dc : 8; + RK_U32 ch_round_dc : 8; + RK_U32 : 8; + } num_5; + + struct { + RK_U32 y1_round_ac : 8; + RK_U32 y2_round_ac : 8; + RK_U32 ch_round_ac : 8; + RK_U32 : 8; + } num_6; + + struct { + RK_U32 y1_dequant_dc : 8; + RK_U32 y2_dequant_dc : 9; + RK_U32 ch_dequant_dc : 8; + RK_U32 filter_level : 6; + RK_U32 : 1; + } num_7; + + struct { + RK_U32 y1_dequant_ac : 9; + RK_U32 y2_dequant_ac : 9; + RK_U32 ch_dequant_ac : 9; + RK_U32 : 5; + } num_8; + + } sw0_26[27]; + + struct { + RK_U32 base_segment_map : 32; + } sw27; + + struct { + RK_U32 b_mode_0_penalty : 12; + RK_U32 : 4; + RK_U32 b_mode_1_penalty : 12; + RK_U32 : 4; + } sw28_32[5]; + + struct { + RK_U32 mode0_penalty : 12; + RK_U32 : 4; + RK_U32 mode1_penalty : 12; + RK_U32 : 4; + } sw33; + + struct { + RK_U32 mode2_penalty : 12; + RK_U32 : 4; + RK_U32 mode3_penalty : 12; + RK_U32 : 4; + } sw34; + + RK_U32 sw35_39[5]; + + struct { + RK_U32 cost_inter : 12; + RK_U32 : 4; + RK_U32 lf_ref_delta0 : 7; + RK_U32 : 1; + RK_U32 lf_mode_delta0 : 7; + RK_U32 : 1; + } sw40; + + struct { + RK_U32 cost_golden_ref : 12; + RK_U32 : 4; + RK_U32 dmv_cost_const : 12; + RK_U32 : 4; + } sw41; + + struct { + RK_U32 lf_ref_delta2 : 7; + RK_U32 : 1; + RK_U32 lf_ref_delta1 : 7; + RK_U32 : 1; + RK_U32 lf_ref_delta3 : 7; + RK_U32 : 9; + } sw42; + + struct { + RK_U32 lf_mode_delta2 : 7; + RK_U32 : 1; + RK_U32 lf_mode_delta1 : 7; + RK_U32 : 1; + RK_U32 lf_mode_delta3 : 7; + RK_U32 : 9; + } sw43; + + struct { + RK_U32 base_partition1 : 32; + } sw44; + + struct { + RK_U32 base_partition2 : 32; + } sw45; + + struct { + RK_U32 intra_area_right : 8; + RK_U32 intra_area_left : 8; + RK_U32 intra_area_bottom : 8; + RK_U32 intra_area_top : 8; + } sw46; + + struct { + RK_U32 cir_interval : 16; + RK_U32 cir_start : 16; + } sw47; + + struct { + RK_U32 base_in_lum : 32; + } sw48; + + struct { + RK_U32 base_in_cb : 32; + } sw49; + + struct { + RK_U32 base_in_cr : 32; + } sw50; + + struct { + RK_U32 strm_hdr_rem1 : 32; + } sw51; + + struct { + RK_U32 strm_hdr_rem2 : 32; + } sw52; + + struct { + RK_U32 strm_buf_limit : 32; + } sw53; + + struct { + RK_U32 val : 32; + } sw54; + + RK_U32 sw55; + + struct { + RK_U32 base_ref_lum : 32; + } sw56; + + struct { + RK_U32 base_ref_chr : 32; + } sw57; + + struct { + RK_U32 : 11; + RK_U32 qp_sum : 21; + } sw58; + + struct { + RK_U32 : 8; + RK_U32 slice_size : 7; + RK_U32 strea_mmode : 1; + RK_U32 inter4_restrict : 1; + RK_U32 transform_8x8 : 1; + RK_U32 : 2; + RK_U32 cabac_enable : 1; + RK_U32 cabac_init_idc : 2; + RK_U32 : 1; + RK_U32 deblocking : 2; + RK_U32 : 2; + RK_U32 disable_qp_mv : 1; + RK_U32 : 3; + } sw59; + + struct { + RK_U32 y_fill : 4; + RK_U32 x_fill : 2; + RK_U32 : 2; + RK_U32 skip_penalty : 8; + RK_U32 start_offset : 6; + RK_U32 : 10; + } sw60; + + struct { + RK_U32 row_length : 14; + RK_U32 : 2; + RK_U32 lum_offset : 3; + RK_U32 : 1; + RK_U32 chr_offset : 3; + RK_U32 : 9; + } sw61; + + struct { + RK_U32 rlc_sum : 23; + RK_U32 : 9; + } sw62; + + struct { + RK_U32 base_rec_lum : 32; + } sw63; + + struct { + RK_U32 base_rec_chr : 32; + } sw64; + + struct { + RK_U32 y1_quant_ac : 14; + RK_U32 y1_zbin_ac : 9; + RK_U32 y1_round_ac : 8; + RK_U32 : 1; + } sw65; + + struct { + RK_U32 y2_quant_dc : 14; + RK_U32 y2_zbin_dc : 9; + RK_U32 y2_round_dc : 8; + RK_U32 : 1; + } sw66; + + struct { + RK_U32 y2_quant_ac : 14; + RK_U32 y2_zbin_ac : 9; + RK_U32 y2_round_ac : 8; + RK_U32 : 1; + } sw67; + + struct { + RK_U32 ch_quant_dc : 14; + RK_U32 ch_zbin_dc : 9; + RK_U32 ch_round_dc : 8; + RK_U32 : 1; + } sw68; + + struct { + RK_U32 ch_quant_ac : 14; + RK_U32 ch_zbin_ac : 9; + RK_U32 ch_round_ac : 8; + RK_U32 : 1; + } sw69; + + struct { + RK_U32 y1_dequant_dc : 8; + RK_U32 y1_dequant_ac : 9; + RK_U32 y2_dequant_dc : 9; + RK_U32 mv_ref_idx : 2 ; + RK_U32 : 4; + } sw70; + + struct { + RK_U32 y2_dequant_ac : 9; + RK_U32 ch_dequant_dc : 8; + RK_U32 ch_dequant_ac : 9; + RK_U32 mv_ref_idx2 : 2; + RK_U32 ref2_enable : 1; + RK_U32 segment_enable : 1; + RK_U32 segment_map_update : 1; + RK_U32 : 1; + } sw71; + + struct { + RK_U32 bool_enc_value : 32; + } sw72; + + struct { + RK_U32 bool_enc_range : 8; + RK_U32 bool_enc_value_bits : 5; + RK_U32 dct_partition_count : 2; + RK_U32 filter_level : 6; + RK_U32 filter_sharpness : 3; + RK_U32 golden_penalty : 8; + } sw73; + + struct { + RK_U32 nal_size_write : 1; + RK_U32 : 1; + RK_U32 input_rot : 2; + RK_U32 input_format : 4; + RK_U32 : 8; + RK_U32 num_slices_ready : 8; + RK_U32 mad_threshold : 6; + RK_U32 : 2; + } sw74; + + struct { + RK_U32 inter_favor : 16; + RK_U32 ip_intra_16_favor : 16; + } sw75; + + struct { + RK_U32 base_ref_lum2 : 32; + } sw76; + + struct { + RK_U32 base_stream : 32; + } sw77; + + struct { + RK_U32 base_control : 32; + } sw78; + + struct { + RK_U32 base_next_lum : 32; + } sw79; + + struct { + RK_U32 base_mv_write : 32; + } sw80; + + struct { + RK_U32 base_cabac_ctx : 32; + } sw81; + + struct { + RK_U32 roi1_right : 8; + RK_U32 roi1_left : 8; + RK_U32 roi1_bottom : 8; + RK_U32 roi1_top : 8; + } sw82; + + struct { + RK_U32 roi2_right : 8; + RK_U32 roi2_left : 8; + RK_U32 roi2_bottom : 8; + RK_U32 roi2_top : 8; + } sw83; + + RK_U32 sw84_93[10]; + + struct { + RK_U32 stab_gmvx : 6; + RK_U32 stab_mode : 2; + RK_U32 stab_minimum : 24; + } sw94; + + struct { + RK_U32 rgb_coeff_a : 16; + RK_U32 rgb_coeff_b : 16; + } sw95; + + struct { + RK_U32 rgb_coeff_c : 16; + RK_U32 rgb_coeff_e : 16; + } sw96; + + struct { + RK_U32 rgb_coeff_f : 16; + RK_U32 : 16; + } sw97; + + struct { + RK_U32 r_mask_msb : 5; + RK_U32 : 3; + RK_U32 g_mask_msb : 5; + RK_U32 : 3; + RK_U32 b_mask_msb : 5; + RK_U32 : 11; + } sw98; + + struct { + RK_U32 split_mv : 1; + RK_U32 dmv_penalty_4p : 10; + RK_U32 dmv_penalty_qp : 10; + RK_U32 dmv_penalty_1p : 10; + RK_U32 : 1; + } sw99; + + struct { + RK_U32 y1_quant_dc : 14; + RK_U32 y1_zbin_dc : 9; + RK_U32 y1_round_dc : 8; + RK_U32 : 1; + } sw100; + + RK_U32 sw101; + + struct { + RK_U32 mvc_inter_view_flag : 1; + RK_U32 mvc_temporal_id : 3; + RK_U32 mvc_priority_id : 3; + RK_U32 mvc_anchor_pic_flag : 1; + RK_U32 mvc_view_id : 3; + RK_U32 split_penalty_4x4 : 9; + RK_U32 zero_mv_favor : 4; + RK_U32 : 8; + } sw102; + + struct { + RK_U32 enable : 1; + RK_U32 : 3; + RK_U32 encoding_mode : 2; + RK_U32 picture_type : 2; + RK_U32 width : 9; + RK_U32 : 3; + RK_U32 height : 9; + RK_U32 : 3; + } sw103; + + struct { + RK_U32 mad_count : 16; + RK_U32 mb_count : 16; + } sw104; + + struct { + RK_U32 val : 32; + } sw105; + + struct { + RK_U32 base_ref_chr2 : 32; + } sw106; + + struct { + RK_U32 split_penalty_8x4 : 10; + RK_U32 split_penalty_8x8 : 10; + RK_U32 split_penalty_16x8 : 10; + RK_U32 : 2; + } sw107; + + struct { + RK_U32 base_prob_count : 32; + } sw108; + + struct { + RK_U32 val : 16; + RK_U32 int_slice_ready : 1; + RK_U32 : 3; + RK_U32 rec_write_disable : 1; + RK_U32 : 3; + RK_U32 mv_write : 1; + RK_U32 : 7; + } sw109; + + RK_U32 sw110_119[10]; + + struct { + RK_U32 penalty_0 : 8; + RK_U32 penalty_1 : 8; + RK_U32 penalty_2 : 8; + RK_U32 penalty_3 : 8; + } sw120_183[64]; + +} Vp8eVepu2Reg_t; + +#endif /*__HAL_VP8E_VEPU2_REG_H__*/ diff --git a/mpp/mpi.cpp b/mpp/mpi.cpp index b6df5740..c0876e7c 100644 --- a/mpp/mpi.cpp +++ b/mpp/mpi.cpp @@ -74,6 +74,9 @@ static MppCodingTypeInfo support_list[] = { #if HAVE_H265E { MPP_CTX_ENC, MPP_VIDEO_CodingHEVC, "enc", "h265", }, #endif +#if HAVE_VP8E + { MPP_CTX_ENC, MPP_VIDEO_CodingVP8, "enc", "vp8", } +#endif }; #define check_mpp_ctx(ctx) _check_mpp_ctx(ctx, __FUNCTION__) diff --git a/osal/inc/mpp_common.h b/osal/inc/mpp_common.h index b970f899..b842d7a8 100644 --- a/osal/inc/mpp_common.h +++ b/osal/inc/mpp_common.h @@ -33,6 +33,10 @@ #define MPP_DIV(a, b) ((b) ? (a) / (b) : (a)) +#define MPP_CLIP3(l, h, v) ((v) < (l) ? (l) : ((v) > (h) ? (h) : (v))) +#define MPP_SIGN(a) ((a) < (0) ? (-1) : (1)) +#define MPP_DIV_SIGN(a, b) (((a) + (MPP_SIGN(a) * (b)) / 2) / (b)) + #define MPP_SWAP(type, a, b) do {type SWAP_tmp = b; b = a; a = SWAP_tmp;} while(0) #define MPP_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) #define MPP_ALIGN(x, a) (((x)+(a)-1)&~((a)-1))