// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
*/
#include "hantro.h"
/*
* probs table with packed
*/
struct vp8_prob_tbl_packed {
u8 prob_mb_skip_false;
u8 prob_intra;
u8 prob_ref_last;
u8 prob_ref_golden;
u8 prob_segment[3 ];
u8 padding0;
u8 prob_luma_16x16_pred_mode[4 ];
u8 prob_chroma_pred_mode[3 ];
u8 padding1;
/* mv prob */
u8 prob_mv_context[2 ][V4L2_VP8_MV_PROB_CNT];
u8 padding2[2 ];
/* coeff probs */
u8 prob_coeffs[4 ][8 ][3 ][V4L2_VP8_COEFF_PROB_CNT];
u8 padding3[96 ];
};
/*
* filter taps taken to 7-bit precision,
* reference RFC6386#Page-16, filters[8][6]
*/
const u32 hantro_vp8_dec_mc_filter[8 ][6 ] = {
{ 0 , 0 , 128 , 0 , 0 , 0 },
{ 0 , -6 , 123 , 12 , -1 , 0 },
{ 2 , -11 , 108 , 36 , -8 , 1 },
{ 0 , -9 , 93 , 50 , -6 , 0 },
{ 3 , -16 , 77 , 77 , -16 , 3 },
{ 0 , -6 , 50 , 93 , -9 , 0 },
{ 1 , -8 , 36 , 108 , -11 , 2 },
{ 0 , -1 , 12 , 123 , -6 , 0 }
};
void hantro_vp8_prob_update(struct hantro_ctx *ctx,
const struct v4l2_ctrl_vp8_frame *hdr)
{
const struct v4l2_vp8_entropy *entropy = &hdr->entropy;
u32 i, j, k;
u8 *dst;
/* first probs */
dst = ctx->vp8_dec.prob_tbl.cpu;
dst[0 ] = hdr->prob_skip_false;
dst[1 ] = hdr->prob_intra;
dst[2 ] = hdr->prob_last;
dst[3 ] = hdr->prob_gf;
dst[4 ] = hdr->segment.segment_probs[0 ];
dst[5 ] = hdr->segment.segment_probs[1 ];
dst[6 ] = hdr->segment.segment_probs[2 ];
dst[7 ] = 0 ;
dst += 8 ;
dst[0 ] = entropy->y_mode_probs[0 ];
dst[1 ] = entropy->y_mode_probs[1 ];
dst[2 ] = entropy->y_mode_probs[2 ];
dst[3 ] = entropy->y_mode_probs[3 ];
dst[4 ] = entropy->uv_mode_probs[0 ];
dst[5 ] = entropy->uv_mode_probs[1 ];
dst[6 ] = entropy->uv_mode_probs[2 ];
dst[7 ] = 0 ; /*unused */
/* mv probs */
dst += 8 ;
dst[0 ] = entropy->mv_probs[0 ][0 ]; /* is short */
dst[1 ] = entropy->mv_probs[1 ][0 ];
dst[2 ] = entropy->mv_probs[0 ][1 ]; /* sign */
dst[3 ] = entropy->mv_probs[1 ][1 ];
dst[4 ] = entropy->mv_probs[0 ][8 + 9 ];
dst[5 ] = entropy->mv_probs[0 ][9 + 9 ];
dst[6 ] = entropy->mv_probs[1 ][8 + 9 ];
dst[7 ] = entropy->mv_probs[1 ][9 + 9 ];
dst += 8 ;
for (i = 0 ; i < 2 ; ++i) {
for (j = 0 ; j < 8 ; j += 4 ) {
dst[0 ] = entropy->mv_probs[i][j + 9 + 0 ];
dst[1 ] = entropy->mv_probs[i][j + 9 + 1 ];
dst[2 ] = entropy->mv_probs[i][j + 9 + 2 ];
dst[3 ] = entropy->mv_probs[i][j + 9 + 3 ];
dst += 4 ;
}
}
for (i = 0 ; i < 2 ; ++i) {
dst[0 ] = entropy->mv_probs[i][0 + 2 ];
dst[1 ] = entropy->mv_probs[i][1 + 2 ];
dst[2 ] = entropy->mv_probs[i][2 + 2 ];
dst[3 ] = entropy->mv_probs[i][3 + 2 ];
dst[4 ] = entropy->mv_probs[i][4 + 2 ];
dst[5 ] = entropy->mv_probs[i][5 + 2 ];
dst[6 ] = entropy->mv_probs[i][6 + 2 ];
dst[7 ] = 0 ; /*unused */
dst += 8 ;
}
/* coeff probs (header part) */
dst = ctx->vp8_dec.prob_tbl.cpu;
dst += (8 * 7 );
for (i = 0 ; i < 4 ; ++i) {
for (j = 0 ; j < 8 ; ++j) {
for (k = 0 ; k < 3 ; ++k) {
dst[0 ] = entropy->coeff_probs[i][j][k][0 ];
dst[1 ] = entropy->coeff_probs[i][j][k][1 ];
dst[2 ] = entropy->coeff_probs[i][j][k][2 ];
dst[3 ] = entropy->coeff_probs[i][j][k][3 ];
dst += 4 ;
}
}
}
/* coeff probs (footer part) */
dst = ctx->vp8_dec.prob_tbl.cpu;
dst += (8 * 55 );
for (i = 0 ; i < 4 ; ++i) {
for (j = 0 ; j < 8 ; ++j) {
for (k = 0 ; k < 3 ; ++k) {
dst[0 ] = entropy->coeff_probs[i][j][k][4 ];
dst[1 ] = entropy->coeff_probs[i][j][k][5 ];
dst[2 ] = entropy->coeff_probs[i][j][k][6 ];
dst[3 ] = entropy->coeff_probs[i][j][k][7 ];
dst[4 ] = entropy->coeff_probs[i][j][k][8 ];
dst[5 ] = entropy->coeff_probs[i][j][k][9 ];
dst[6 ] = entropy->coeff_probs[i][j][k][10 ];
dst[7 ] = 0 ; /*unused */
dst += 8 ;
}
}
}
}
int hantro_vp8_dec_init(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct hantro_aux_buf *aux_buf;
unsigned int mb_width, mb_height;
size_t segment_map_size;
int ret;
/* segment map table size calculation */
mb_width = DIV_ROUND_UP(ctx->dst_fmt.width, 16 );
mb_height = DIV_ROUND_UP(ctx->dst_fmt.height, 16 );
segment_map_size = round_up(DIV_ROUND_UP(mb_width * mb_height, 4 ), 64 );
/*
* In context init the dma buffer for segment map must be allocated.
* And the data in segment map buffer must be set to all zero.
*/
aux_buf = &ctx->vp8_dec.segment_map;
aux_buf->size = segment_map_size;
aux_buf->cpu = dma_alloc_coherent(vpu->dev, aux_buf->size,
&aux_buf->dma, GFP_KERNEL);
if (!aux_buf->cpu)
return -ENOMEM;
/*
* Allocate probability table buffer,
* total 1208 bytes, 4K page is far enough.
*/
aux_buf = &ctx->vp8_dec.prob_tbl;
aux_buf->size = sizeof (struct vp8_prob_tbl_packed);
aux_buf->cpu = dma_alloc_coherent(vpu->dev, aux_buf->size,
&aux_buf->dma, GFP_KERNEL);
if (!aux_buf->cpu) {
ret = -ENOMEM;
goto err_free_seg_map;
}
return 0 ;
err_free_seg_map:
dma_free_coherent(vpu->dev, ctx->vp8_dec.segment_map.size,
ctx->vp8_dec.segment_map.cpu,
ctx->vp8_dec.segment_map.dma);
return ret;
}
void hantro_vp8_dec_exit(struct hantro_ctx *ctx)
{
struct hantro_vp8_dec_hw_ctx *vp8_dec = &ctx->vp8_dec;
struct hantro_dev *vpu = ctx->dev;
dma_free_coherent(vpu->dev, vp8_dec->segment_map.size,
vp8_dec->segment_map.cpu, vp8_dec->segment_map.dma);
dma_free_coherent(vpu->dev, vp8_dec->prob_tbl.size,
vp8_dec->prob_tbl.cpu, vp8_dec->prob_tbl.dma);
}
Messung V0.5 in Prozent C=96 H=94 G=94
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-08)
¤
*© Formatika GbR, Deutschland