[avs]: Add avs module

NOTE: I frame header decoding should check stream version.

Signed-off-by: Ding Wei <leo.ding@rock-chips.com>
Signed-off-by: Yandong Lin <yandong.lin@rock-chips.com>
Signed-off-by: Johnson Ding <johnson.ding@rock-chips.com>
Change-Id: I1c8276f4499d73e3b60d582890037dec376e136f
This commit is contained in:
Yandong Lin
2021-11-03 10:45:53 +08:00
committed by Herman Chen
parent a9cb2cff35
commit 3adde926e2
28 changed files with 3228 additions and 850 deletions

View File

@@ -47,7 +47,7 @@ typedef enum {
VPU_DEC_HEVC = 0x4,
VPU_DEC_RKV = 0x5,
VPU_ENC_RKV = 0x6,
VPU_DEC_AVS = 0x7,
VPU_DEC_AVSPLUS = 0x7,
VPU_ENC_VEPU22 = 0x8,
VPU_TYPE_BUTT ,
} VPU_CLIENT_TYPE;

View File

@@ -240,7 +240,8 @@ typedef enum OMX_RK_VIDEO_CODINGTYPE {
OMX_RK_VIDEO_CodingDIVX3, /**< DIVX3 */
OMX_RK_VIDEO_CodingVP6,
OMX_RK_VIDEO_CodingHEVC, /**< H.265/HEVC */
OMX_RK_VIDEO_CodingAVS, /**< AVS+ */
OMX_RK_VIDEO_CodingAVSPLUS, /**< AVS+ profile 0x48 */
OMX_RK_VIDEO_CodingAVS, /**< AVS profile 0x20 */
OMX_RK_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
OMX_RK_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
OMX_RK_VIDEO_CodingMax = 0x7FFFFFFF

View File

@@ -1,5 +1,4 @@
/*
*
* Copyright 2015 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -49,8 +48,7 @@ MPP_RET avsd_deinit(void *decoder)
AVSD_PARSE_TRACE("In.");
mpp_packet_deinit(&p_dec->task_pkt);
MPP_FREE(p_dec->p_stream->pbuf);
MPP_FREE(p_dec->p_header->pbuf);
MPP_FREE(p_dec->streambuf);
MPP_FREE(p_dec->mem);
__RETURN:
@@ -85,24 +83,25 @@ MPP_RET avsd_init(void *decoder, ParserCfg *init)
mpp_buf_slot_setup(p_dec->frame_slots, 12);
p_dec->mem = mpp_calloc(AvsdMemory_t, 1);
MEM_CHECK(ret, p_dec->mem);
p_dec->p_header = &p_dec->mem->headerbuf;
p_dec->p_header->size = MAX_HEADER_SIZE;
p_dec->p_header->pbuf = mpp_malloc(RK_U8, p_dec->p_header->size);
MEM_CHECK(ret, p_dec->p_header->pbuf);
p_dec->syn = &p_dec->mem->syntax;
p_dec->p_stream = &p_dec->mem->streambuf;
p_dec->p_stream->size = MAX_STREAM_SIZE;
p_dec->p_stream->pbuf = mpp_malloc(RK_U8, p_dec->p_stream->size);
MEM_CHECK(ret, p_dec->p_stream->pbuf);
mpp_packet_init(&p_dec->task_pkt, p_dec->p_stream->pbuf, p_dec->p_stream->size);
p_dec->stream_size = MAX_STREAM_SIZE;
p_dec->streambuf = mpp_malloc(RK_U8, p_dec->stream_size);
MEM_CHECK(ret, p_dec->streambuf);
mpp_packet_init(&p_dec->task_pkt, p_dec->streambuf, p_dec->stream_size);
mpp_packet_set_length(p_dec->task_pkt, 0);
MEM_CHECK(ret, p_dec->task_pkt);
for (i = 0; i < 3; i++) {
memset(&p_dec->mem->save[i], 0, sizeof(AvsdFrame_t));
p_dec->mem->save[i].slot_idx = -1;
AvsdFrame_t *frm = &p_dec->mem->save[i];
memset(frm, 0, sizeof(*frm));
frm->idx = i;
frm->slot_idx = -1;
}
p_dec->bx = &p_dec->mem->bitctx;
p_dec->need_split = 1;
__RETURN:
AVSD_PARSE_TRACE("Out.");
return ret = MPP_OK;
@@ -125,12 +124,20 @@ MPP_RET avsd_reset(void *decoder)
AVSD_PARSE_TRACE("In.");
avsd_reset_parameters(p_dec);
p_dec->got_vsh = 0;
p_dec->got_ph = 0;
p_dec->got_keyframe = 0;
p_dec->vec_flag = 0;
p_dec->got_eos = 0;
p_dec->left_length = 0;
p_dec->state = 0xFFFFFFFF;
p_dec->vop_header_found = 0;
mpp_packet_set_length(p_dec->task_pkt, 0);
mpp_packet_set_flag(p_dec->task_pkt, 0);
AVSD_PARSE_TRACE("Out.");
(void)p_dec;
(void)decoder;
return ret = MPP_OK;
}
@@ -149,6 +156,10 @@ MPP_RET avsd_flush(void *decoder)
avsd_reset_parameters(p_dec);
p_dec->got_keyframe = 0;
p_dec->vec_flag = 0;
p_dec->got_eos = 0;
p_dec->left_length = 0;
p_dec->state = 0xFFFFFFFF;
p_dec->vop_header_found = 0;
AVSD_PARSE_TRACE("Out.");
(void)p_dec;
@@ -165,13 +176,18 @@ MPP_RET avsd_flush(void *decoder)
MPP_RET avsd_control(void *decoder, MpiCmd cmd_type, void *param)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
AVSD_PARSE_TRACE("In.");
switch (cmd_type) {
case MPP_DEC_SET_DISABLE_ERROR: {
p_dec->disable_error = *((RK_U32 *)param);
} break;
default : {
} break;
}
(void)decoder;
(void)cmd_type;
(void)param;
AVSD_PARSE_TRACE("Out.");
return ret = MPP_OK;
}
@@ -186,77 +202,95 @@ MPP_RET avsd_control(void *decoder, MpiCmd cmd_type, void *param)
MPP_RET avsd_prepare(void *decoder, MppPacket pkt, HalDecTask *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
AVSD_PARSE_TRACE("In.");
INP_CHECK(ret, !decoder && !pkt && !task);
if (p_dec->has_get_eos
|| (mpp_packet_get_flag(pkt) & MPP_PACKET_FLAG_EXTRA_DATA)) {
AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder;
RK_U8 *pos = mpp_packet_get_pos(pkt);
size_t length = mpp_packet_get_length(pkt);
RK_U32 eos = mpp_packet_get_eos(pkt);
task->valid = 0;
if (p_dec->got_eos) {
AVSD_DBG(AVSD_DBG_INPUT, "got eos packet.\n");
mpp_packet_set_length(pkt, 0);
goto __RETURN;
}
AVSD_DBG(AVSD_DBG_INPUT, "[pkt_in_timeUs] in_pts=%lld, pkt_eos=%d, len=%d, pkt_no=%d\n",
mpp_packet_get_pts(pkt), (RK_U32)mpp_packet_get_eos(pkt), (RK_U32)mpp_packet_get_length(pkt), (RK_U32)p_dec->pkt_no);
AVSD_DBG(AVSD_DBG_INPUT, "[pkt_in] pts=%lld, eos=%d, len=%d, pkt_no=%d\n",
mpp_packet_get_pts(pkt), eos, (RK_U32)length, (RK_U32)p_dec->pkt_no);
p_dec->pkt_no++;
if (mpp_packet_get_eos(pkt)) {
if (mpp_packet_get_length(pkt) < 4) {
avsd_flush(decoder);
}
p_dec->has_get_eos = 1;
task->flags.eos = p_dec->has_get_eos;
p_dec->got_eos = 1;
task->flags.eos = p_dec->got_eos;
goto __RETURN;
}
if (mpp_packet_get_length(pkt) > MAX_STREAM_SIZE) {
AVSD_DBG(AVSD_DBG_ERROR, "[pkt_in_timeUs] input error, stream too large");
mpp_packet_set_length(pkt, 0);
ret = MPP_NOK;
goto __FAILED;
goto __RETURN;
}
task->valid = 0;
mpp_packet_set_length(p_dec->task_pkt, p_dec->left_length);
RK_U32 total_length = MPP_ALIGN(p_dec->left_length + length, 16) + 64;
if (total_length > p_dec->stream_size) {
do {
(ret = avsd_parse_prepare(p_dec, pkt, task));
p_dec->stream_size <<= 1;
} while (total_length > p_dec->stream_size);
} while (mpp_packet_get_length(pkt) && !task->valid);
RK_U8 *dst = mpp_malloc_size(RK_U8, p_dec->stream_size);
mpp_assert(dst);
if (task->valid) {
//!< bit stream
RK_U32 align_len = MPP_ALIGN(p_dec->p_stream->len + 32, 16);
mpp_assert(p_dec->p_stream->size > align_len);
memset(p_dec->p_stream->pbuf + p_dec->p_stream->len,
0, align_len - p_dec->p_stream->len);
p_dec->syn->bitstream_size = align_len;
p_dec->syn->bitstream = p_dec->p_stream->pbuf;
mpp_packet_set_data(p_dec->task_pkt, p_dec->syn->bitstream);
mpp_packet_set_length(p_dec->task_pkt, p_dec->syn->bitstream_size);
mpp_packet_set_size(p_dec->task_pkt, p_dec->p_stream->size);
mpp_packet_set_pts(p_dec->task_pkt, mpp_packet_get_pts(pkt));
mpp_packet_set_dts(p_dec->task_pkt, mpp_packet_get_dts(pkt));
task->input_packet = p_dec->task_pkt;
p_dec->p_stream->len = 0;
p_dec->p_header->len = 0;
} else {
task->input_packet = NULL;
if (p_dec->left_length > 0) {
memcpy(dst, p_dec->streambuf, p_dec->left_length);
}
mpp_free(p_dec->streambuf);
p_dec->streambuf = dst;
mpp_packet_set_data(p_dec->task_pkt, p_dec->streambuf);
mpp_packet_set_size(p_dec->task_pkt, p_dec->stream_size);
}
if (!p_dec->need_split) {
p_dec->got_eos = eos;
// empty eos packet
if (eos && (length < 4)) {
avsd_flush(decoder);
goto __RETURN;
}
// copy packet direct
memcpy(p_dec->streambuf, pos, length);
mpp_packet_set_data(p_dec->task_pkt, p_dec->streambuf);
mpp_packet_set_length(p_dec->task_pkt, length);
mpp_packet_set_pts(p_dec->task_pkt, mpp_packet_get_pts(pkt));
// set input packet length to 0 here
mpp_packet_set_length(pkt, 0);
/* this step will enable the task and goto parse stage */
task->valid = 1;
} else {
/* Split packet mode */
if (MPP_OK == avsd_parser_split(p_dec, p_dec->task_pkt, pkt)) {
p_dec->left_length = 0;
task->valid = 1;
} else {
task->valid = 0;
p_dec->left_length = mpp_packet_get_length(p_dec->task_pkt);
}
p_dec->got_eos = mpp_packet_get_eos(p_dec->task_pkt);
}
task->input_packet = p_dec->task_pkt;
task->flags.eos = p_dec->got_eos;
__RETURN:
(void)decoder;
(void)pkt;
(void)task;
AVSD_PARSE_TRACE("Out.");
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief
@@ -280,7 +314,10 @@ MPP_RET avsd_parse(void *decoder, HalDecTask *task)
avsd_commit_syntaxs(p_dec->syn, task);
avsd_update_dpb(p_dec);
}
if (p_dec->disable_error) {
task->flags.ref_err = 0;
task->flags.parse_err = 0;
}
AVSD_PARSE_TRACE("Out.");
return ret = MPP_OK;
@@ -298,11 +335,9 @@ MPP_RET avsd_callback(void *decoder, void *info)
DecCbHalDone *ctx = (DecCbHalDone *)info;
AVSD_PARSE_TRACE("In.");
{
if (!p_dec->disable_error) {
MppFrame mframe = NULL;
HalDecTask *task_dec = (HalDecTask *)ctx->task;
AVSD_DBG(AVSD_DBG_CALLBACK, "reg[1]=%08x, ref=%d, dpberr=%d, harderr-%d\n",
ctx->regs[1], task_dec->flags.used_for_ref, task_dec->flags.ref_err, ctx->hard_err);
mpp_buf_slot_get_prop(p_dec->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe);
if (mframe) {
@@ -316,8 +351,7 @@ MPP_RET avsd_callback(void *decoder, void *info)
}
}
AVSD_PARSE_TRACE("Out.");
(void)p_dec;
(void)ctx;
return ret = MPP_OK;
}
/*!
@@ -327,6 +361,21 @@ MPP_RET avsd_callback(void *decoder, void *info)
***********************************************************************
*/
const ParserApi api_avsd_parser = {
.name = "avsd_parse",
.coding = MPP_VIDEO_CodingAVS,
.ctx_size = sizeof(AvsdCtx_t),
.flag = 0,
.init = avsd_init,
.deinit = avsd_deinit,
.prepare = avsd_prepare,
.parse = avsd_parse,
.reset = avsd_reset,
.flush = avsd_flush,
.control = avsd_control,
.callback = avsd_callback,
};
const ParserApi api_avsd_plus_parser = {
.name = "avsd_parse",
.coding = MPP_VIDEO_CodingAVSPLUS,
.ctx_size = sizeof(AvsdCtx_t),
@@ -340,4 +389,3 @@ const ParserApi api_avsd_parser = {
.control = avsd_control,
.callback = avsd_callback,
};

View File

@@ -1,5 +1,4 @@
/*
*
* Copyright 2015 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,57 +26,6 @@
#include "avsd_api.h"
#include "avsd_parse.h"
static MPP_RET add_nalu_header(AvsdCtx_t *p_dec, RK_U32 header)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdStreamBuf_t *p_buf = p_dec->p_header;
RK_U32 add_size = sizeof(AvsdNalu_t);
if ((p_buf->len + add_size) > p_buf->size) {
mpp_err_f("buffer is larger than %d", p_buf->size);
goto __FAILED;
}
p_dec->nal = (AvsdNalu_t *)&p_buf->pbuf[p_buf->len];
p_dec->nal->eof = 0;
p_dec->nal->header = header;
p_dec->nal->pdata = NULL;
p_dec->nal->length = 0;
p_dec->nal->start_pos = 4;
p_buf->len += add_size;
return ret = MPP_OK;
__FAILED:
return ret;
}
static MPP_RET store_cur_nalu(AvsdCtx_t *p_dec, RK_U8 *p_start, RK_U32 nalu_len)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdStreamBuf_t *p_buf = NULL;
AvsdNalu_t *p_nalu = p_dec->nal;
if (p_nalu->header >= SLICE_MIN_START_CODE
&& p_nalu->header <= SLICE_MAX_START_CODE) {
p_buf = p_dec->p_stream;
} else {
p_buf = p_dec->p_header;
}
if ((p_buf->len + nalu_len) > p_buf->size) {
mpp_err_f("buffer is larger than %d", p_buf->size);
goto __FAILED;
}
p_nalu->length += nalu_len;
p_nalu->pdata = &p_buf->pbuf[p_buf->len];
memcpy(p_nalu->pdata, p_start, nalu_len);
p_buf->len += nalu_len;
return ret = MPP_OK;
__FAILED:
return ret;
}
static MPP_RET get_sequence_header(BitReadCtx_t *bitctx, AvsdSeqHeader_t *vsh)
{
MPP_RET ret = MPP_ERR_UNKNOW;
@@ -277,26 +225,45 @@ static MPP_RET get_i_picture_header(BitReadCtx_t *bitctx, AvsdSeqHeader_t *vsh,
if (ph->time_code_flag) {
READ_BITS(bitctx, 24, &ph->time_code);
}
SKIP_BITS(bitctx, 1);
READ_BITS(bitctx, 8, &ph->picture_distance);
vsh->version = 0;
/* check stream version */
if (vsh->low_delay) {
READ_UE(bitctx, &ph->bbv_check_times);
}
READ_ONEBIT(bitctx, &ph->progressive_frame);
if (!ph->progressive_frame) {
READ_ONEBIT(bitctx, &ph->picture_structure);
vsh->version = 1;
} else {
ph->picture_structure = 1; //!< frame picture
SHOW_BITS(bitctx, 9, &val_temp);
if (!(val_temp & 1)) {
vsh->version = 1;
} else {
SHOW_BITS(bitctx, 11, &val_temp);
if (val_temp & 3)
vsh->version = 1;
}
}
if (vsh->version > 0)
SKIP_BITS(bitctx, 1); // marker bit
READ_BITS(bitctx, 8, &ph->picture_distance);
if (vsh->low_delay)
READ_UE(bitctx, &ph->bbv_check_times);
READ_ONEBIT(bitctx, &ph->progressive_frame);
ph->picture_structure = 1; // default frame
if (!ph->progressive_frame)
READ_ONEBIT(bitctx, &ph->picture_structure);
READ_ONEBIT(bitctx, &ph->top_field_first);
READ_ONEBIT(bitctx, &ph->repeat_first_field);
READ_ONEBIT(bitctx, &ph->fixed_picture_qp);
READ_BITS(bitctx, 6, &ph->picture_qp);
if (!ph->progressive_frame && !ph->picture_structure) {
READ_ONEBIT(bitctx, &ph->skip_mode_flag);
} else {
ph->skip_mode_flag = 0;
}
if (!ph->progressive_frame && !ph->picture_structure)
READ_ONEBIT(bitctx, &ph->skip_mode_flag);
READ_BITS(bitctx, 4, &val_temp); //!< reserve 4 bits
if (val_temp) {
AVSD_DBG(AVSD_DBG_WARNNING, "reserve bits not equal to zeros.\n");
@@ -374,7 +341,10 @@ __FAILED:
static void reset_one_save(AvsdFrame_t *p)
{
if (p) {
RK_U32 idx = p->idx;
memset(p, 0, sizeof(AvsdFrame_t));
p->idx = idx;
p->slot_idx = -1;
}
}
@@ -392,7 +362,7 @@ static AvsdFrame_t *get_one_save(AvsdCtx_t *p_dec, HalDecTask *task)
}
}
if (!p_cur) {
AVSD_DBG(AVSD_DBG_WARNNING, "error, mem_save dpb has not get.\n");
mpp_err("mem_save dpb %d slots has not get\n", MPP_ARRAY_ELEMS(p_dec->mem->save));
goto __FAILED;
}
(void)task;
@@ -409,8 +379,7 @@ static MPP_RET set_frame_unref(AvsdCtx_t *pdec, AvsdFrame_t *p)
if (p && p->slot_idx >= 0) {
mpp_buf_slot_clr_flag(pdec->frame_slots, p->slot_idx, SLOT_CODEC_USE);
memset(p, 0, sizeof(AvsdFrame_t));
p->slot_idx = -1;
reset_one_save(p);
}
return ret = MPP_OK;
@@ -450,11 +419,13 @@ MPP_RET avsd_reset_parameters(AvsdCtx_t *p_dec)
p_dec->cur = NULL;
p_dec->dpb[0] = NULL;
p_dec->dpb[1] = NULL;
p_dec->has_get_eos = 0;
for (i = 0; i < MPP_ARRAY_ELEMS(p_dec->mem->save); i++) {
memset(&p_dec->mem->save[i], 0, sizeof(AvsdFrame_t));
p_dec->mem->save[i].slot_idx = -1;
AvsdFrame_t *frm = &p_dec->mem->save[i];
memset(frm, 0, sizeof(*frm));
frm->idx = i;
frm->slot_idx = -1;
}
return MPP_OK;
@@ -676,6 +647,10 @@ MPP_RET avsd_fill_parameters(AvsdCtx_t *p_dec, AvsdSyntax_t *syn)
pp->noForwardReferenceFlag = p_dec->ph.no_forward_reference_flag;
pp->pbFieldEnhancedFlag = p_dec->ph.pb_field_enhanced_flag;
//!< set stream offset
syn->bitstream_size = p_dec->cur->stream_len;
syn->bitstream_offset = p_dec->cur->stream_offset;
return MPP_OK;
}
/*!
@@ -684,73 +659,71 @@ MPP_RET avsd_fill_parameters(AvsdCtx_t *p_dec, AvsdSyntax_t *syn)
* prepare function for parser
***********************************************************************
*/
MPP_RET avsd_parse_prepare(AvsdCtx_t *p_dec, MppPacket *pkt, HalDecTask *task)
MPP_RET avsd_parser_split(AvsdCtx_t *p, MppPacket *dst, MppPacket *src)
{
MPP_RET ret = MPP_ERR_UNKNOW;
RK_U8 *p_curdata = NULL;
RK_U8 *p_start = NULL; //!< store nalu start
RK_U32 nalu_len = 0;
RK_U8 got_frame_flag = 0;
RK_U8 got_nalu_flag = 0;
RK_U32 pkt_length = 0;
MPP_RET ret = MPP_NOK;
AVSD_PARSE_TRACE("In.\n");
RK_U32 prefix = 0xFFFFFFFF;
RK_U8 *src_buf = (RK_U8 *)mpp_packet_get_pos(src);
RK_U32 src_len = (RK_U32)mpp_packet_get_length(src);
RK_U32 src_eos = mpp_packet_get_eos(src);
RK_S64 src_pts = mpp_packet_get_pts(src);
RK_U8 *dst_buf = (RK_U8 *)mpp_packet_get_data(dst);
RK_U32 dst_len = (RK_U32)mpp_packet_get_length(dst);
RK_U32 src_pos = 0;
AVSD_PARSE_TRACE("In.");
//!< check input
if (mpp_packet_get_length(pkt) < 4) {
AVSD_DBG(AVSD_DBG_WARNNING, "input have no stream.");
mpp_packet_set_length(pkt, 0);
goto __RETURN;
// find the began of the vop
if (!p->vop_header_found) {
// add last startcode to the new frame data
if ((dst_len < sizeof(p->state))
&& ((p->state & 0x00FFFFFF) == 0x000001)) {
dst_buf[0] = 0;
dst_buf[1] = 0;
dst_buf[2] = 1;
dst_len = 3;
}
pkt_length = (RK_U32)mpp_packet_get_length(pkt);
p_curdata = p_start = (RK_U8 *)mpp_packet_get_pos(pkt);
while (pkt_length > 0) {
//!< found next nalu start code
if ((prefix & 0xFFFFFF00) == 0x00000100) {
if (got_nalu_flag) {
nalu_len = (RK_U32)(p_curdata - p_start) - 4;
FUN_CHECK(ret = store_cur_nalu(p_dec, p_start, nalu_len));
}
FUN_CHECK(ret = add_nalu_header(p_dec, prefix));
p_start = p_curdata - 4;
got_nalu_flag = 1;
}
//!< found next picture start code
if (prefix == I_PICUTRE_START_CODE || prefix == PB_PICUTRE_START_CODE) {
task->valid = 1;
if (got_frame_flag) {
p_dec->nal->eof = 1;
pkt_length += 4;
while (src_pos < src_len) {
p->state = (p->state << 8) | src_buf[src_pos];
dst_buf[dst_len++] = src_buf[src_pos++];
if (p->state == I_PICUTRE_START_CODE ||
p->state == PB_PICUTRE_START_CODE) {
p->vop_header_found = 1;
mpp_packet_set_pts(dst, src_pts);
break;
}
got_frame_flag = 1;
}
}
prefix = (prefix << 8) | (*p_curdata);
p_curdata++;
pkt_length--;
}
//!< reach the packet end
if (!pkt_length) {
nalu_len = (RK_U32)(p_curdata - p_start);
FUN_CHECK(ret = store_cur_nalu(p_dec, p_start, nalu_len));
if (task->valid) {
FUN_CHECK(ret = add_nalu_header(p_dec, 0));
p_dec->nal->eof = 1;
// find the end of the vop
if (p->vop_header_found) {
while (src_pos < src_len) {
p->state = (p->state << 8) | src_buf[src_pos];
dst_buf[dst_len++] = src_buf[src_pos++];
if ((p->state & 0x00FFFFFF) == 0x000001) {
if (src_buf[src_pos] > (SLICE_MAX_START_CODE & 0xFF) &&
src_buf[src_pos] != (USER_DATA_CODE & 0xFF)) {
dst_len -= 3;
p->vop_header_found = 0;
ret = MPP_OK; // split complete
break;
}
}
//!< reset position
pkt_length = (RK_U32)mpp_packet_get_length(pkt) - pkt_length;
mpp_packet_set_pos(pkt, (RK_U8 *)mpp_packet_get_pos(pkt) + pkt_length);
}
}
// the last packet
if (src_eos && src_pos >= src_len) {
mpp_packet_set_eos(dst);
ret = MPP_OK;
}
__RETURN:
AVSD_PARSE_TRACE("Out.");
AVSD_DBG(AVSD_DBG_INPUT, "[pkt_in] vop_header_found= %d, dst_len=%d, src_pos=%d\n",
p->vop_header_found, dst_len, src_pos);
// reset the src and dst
mpp_packet_set_length(dst, dst_len);
mpp_packet_set_pos(src, src_buf + src_pos);
AVSD_PARSE_TRACE("out.\n");
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
@@ -762,32 +735,38 @@ __FAILED:
MPP_RET avsd_parse_stream(AvsdCtx_t *p_dec, HalDecTask *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
RK_U32 startcode = 0xFF;
RK_U32 pic_type = 0;
RK_U32 got_slice = 0;
RK_U8 pic_type = 0;
AvsdNalu_t *p_nalu = (AvsdNalu_t *)p_dec->p_header->pbuf;
RK_U8 *data = (RK_U8 *)mpp_packet_get_data(task->input_packet);
RK_S32 length = (RK_S32)mpp_packet_get_length(task->input_packet);
task->valid = 0;
while (!p_nalu->eof) {
RK_U32 startcode = p_nalu->header;
mpp_set_bitread_ctx(p_dec->bx, data, length);
AVSD_DBG(AVSD_DBG_SYNTAX, "bytes_left_=%d\n", p_dec->bx->bytes_left_);
while (p_dec->bx->bytes_left_ && !got_slice) {
RK_S32 tmp = 0;
mpp_align_get_bits(p_dec->bx);
mpp_read_bits(p_dec->bx, 8, &tmp);
startcode = (startcode << 8) | tmp;
if ((startcode & 0xFFFFFF00) != 0x100)
continue;
AVSD_DBG(AVSD_DBG_SYNTAX, "startcode=%08x\n", startcode);
if (startcode >= SLICE_MIN_START_CODE && startcode <= SLICE_MAX_START_CODE) {
p_nalu++;
} else {
memset(&p_dec->bitctx, 0, sizeof(BitReadCtx_t));
mpp_set_bitread_ctx(&p_dec->bitctx, p_nalu->pdata + p_nalu->start_pos, p_nalu->length);
p_nalu = (AvsdNalu_t *)(p_nalu->pdata + p_nalu->length);
}
if (startcode != VIDEO_SEQUENCE_START_CODE && !p_dec->got_vsh) {
// when has not got sequence header, then do nothing
if (!p_dec->got_vsh &&
startcode != VIDEO_SEQUENCE_START_CODE) {
AVSD_DBG(AVSD_DBG_WARNNING, "when has not got sequence header, then do nothing\n");
continue;
}
//continue;
switch (startcode) {
case VIDEO_SEQUENCE_START_CODE:
ret = get_sequence_header(&p_dec->bitctx, &p_dec->vsh);
ret = get_sequence_header(p_dec->bx, &p_dec->vsh);
if (ret == MPP_OK) {
p_dec->got_vsh = 1;
}
AVSD_DBG(AVSD_DBG_WARNNING, "got vsh %d\n", p_dec->got_vsh);
break;
case VIDEO_SEQUENCE_END_CODE:
break;
@@ -797,59 +776,66 @@ MPP_RET avsd_parse_stream(AvsdCtx_t *p_dec, HalDecTask *task)
p_dec->vec_flag = 0;
break;
case I_PICUTRE_START_CODE:
AVSD_DBG(AVSD_DBG_WARNNING, "got I picture start code\n");
if (!p_dec->got_keyframe) {
avsd_reset_parameters(p_dec);
p_dec->got_keyframe = 1;
}
ret = get_i_picture_header(&p_dec->bitctx, &p_dec->vsh, &p_dec->ph);
ret = get_i_picture_header(p_dec->bx, &p_dec->vsh, &p_dec->ph);
if (ret == MPP_OK) {
p_dec->cur = get_one_save(p_dec, task);
p_dec->got_ph = 1;
}
p_dec->cur->pic_type = pic_type = I_PICTURE;
p_dec->vec_flag++;
break;
case EXTENSION_START_CODE:
ret = get_extension_header(&p_dec->bitctx, &p_dec->ext);
ret = get_extension_header(p_dec->bx, &p_dec->ext);
break;
case PB_PICUTRE_START_CODE:
AVSD_DBG(AVSD_DBG_WARNNING, "got PB picture start code\n");
if (!p_dec->got_keyframe) {
avsd_reset_parameters(p_dec);
break;
}
ret = get_pb_picture_header(&p_dec->bitctx, &p_dec->vsh, &p_dec->ph);
ret = get_pb_picture_header(p_dec->bx, &p_dec->vsh, &p_dec->ph);
if (ret == MPP_OK) {
p_dec->cur = get_one_save(p_dec, task);
p_dec->got_ph = 1;
}
p_dec->cur->pic_type = pic_type = p_dec->ph.picture_coding_type;
p_dec->vec_flag += (p_dec->vec_flag == 1 && pic_type == P_PICTURE);
break;
default:
if (!p_dec->cur
|| (pic_type == P_PICTURE && !p_dec->dpb[0])
|| (pic_type == B_PICTURE && !p_dec->dpb[0])
|| (pic_type == B_PICTURE && !p_dec->dpb[1] && !p_dec->vsh.low_delay)
|| (pic_type == P_PICTURE && p_dec->vec_flag < 1)
|| (pic_type == B_PICTURE && p_dec->vec_flag < 2)) {
mpp_err_f("missing refer frame.\n");
ret = MPP_NOK;
if (p_dec->cur
&& startcode >= SLICE_MIN_START_CODE
&& startcode <= SLICE_MAX_START_CODE) {
got_slice = 1;
p_dec->cur->stream_len = length;
p_dec->cur->stream_offset = p_dec->bx->used_bits / 8 - 4;
task->valid = p_dec->got_vsh && p_dec->got_ph;
AVSD_DBG(AVSD_DBG_SYNTAX, "offset=%d,got_vsh=%d, got_ph=%d, task->valid=%d\n",
p_dec->cur->stream_offset, p_dec->got_vsh, p_dec->got_ph, task->valid);
}
if ((pic_type == P_PICTURE && !p_dec->dpb[0]) ||
(pic_type == B_PICTURE && !p_dec->dpb[0]) ||
(pic_type == B_PICTURE && !p_dec->dpb[1] && !p_dec->vsh.low_delay) ||
(pic_type == P_PICTURE && p_dec->vec_flag < 1) ||
(pic_type == B_PICTURE && p_dec->vec_flag < 2)) {
AVSD_DBG(AVSD_DBG_REF, "missing refer frame.\n");
if (!p_dec->disable_error)
goto __FAILED;
}
if (startcode >= SLICE_MIN_START_CODE
&& startcode <= SLICE_MAX_START_CODE) {
task->valid = 1;
}
break;
}
}
return ret = MPP_OK;
if (!task->valid)
goto __FAILED;
return MPP_OK;
__FAILED:
task->valid = 0;
reset_one_save(p_dec->cur);
return ret;
return MPP_NOK;
}

View File

@@ -32,6 +32,8 @@
#define AVSD_DBG_INPUT (0x00000010) //!< input packet
#define AVSD_DBG_TIME (0x00000020) //!< input packet
#define AVSD_DBG_SYNTAX (0x00000040)
#define AVSD_DBG_REF (0x00000080)
#define AVSD_DBG_CALLBACK (0x00008000)
@@ -76,7 +78,6 @@ if ((val) < 0) {\
goto __FAILED; \
}} while (0)
#define MAX_HEADER_SIZE (2*1024)
#define MAX_STREAM_SIZE (2*1024*1024)
//!< NALU type
@@ -96,7 +97,6 @@ if ((val) < 0) {\
#define VIDEO_TIME_CODE 0x000001E0
#define EDGE_SIZE 16
#define MB_SIZE 16
#define YUV420 0
@@ -108,20 +108,11 @@ enum avsd_picture_type_e {
B_PICTURE = 2
};
typedef struct avsd_nalu_t {
RK_U32 header;
RK_U32 size;
RK_U32 length;
RK_U8 *pdata;
RK_U8 start_pos;
RK_U8 eof; //!< end of frame stream
} AvsdNalu_t;
typedef struct avsd_sequence_header_t {
RK_U8 profile_id;
RK_U8 level_id;
RK_U8 progressive_sequence;
RK_U8 version;
RK_U32 horizontal_size;
RK_U32 vertical_size;
@@ -153,7 +144,7 @@ typedef struct avsd_picture_header {
RK_U8 picture_coding_type;
RK_U8 time_code_flag;
RK_U32 time_code;
RK_U8 picture_distance;
RK_U8 picture_distance; // poc
RK_U32 bbv_check_times;
RK_U8 progressive_frame;
RK_U8 picture_structure;
@@ -187,71 +178,66 @@ typedef struct avsd_picture_header {
typedef struct avsd_frame_t {
RK_U32 valid;
RK_U32 idx;
RK_U32 pic_type;
RK_U32 frame_mode; //!< set mpp frame flag
RK_U32 width;
RK_U32 height;
RK_U32 ver_stride;
RK_U32 hor_stride;
RK_S64 pts;
RK_S64 dts;
RK_S32 stream_len;
RK_S32 stream_offset;
RK_U32 had_display;
RK_S32 slot_idx;
} AvsdFrame_t;
typedef struct avsd_stream_buf_t {
RK_U8 *pbuf;
RK_U32 size;
RK_U32 len;
} AvsdStreamBuf_t;
typedef struct avsd_memory_t {
struct avsd_stream_buf_t headerbuf;
struct avsd_stream_buf_t streambuf;
struct avsd_syntax_t syntax;
struct avsd_frame_t save[3];
BitReadCtx_t bitctx;
} AvsdMemory_t;
//!< decoder parameters
typedef struct avs_dec_ctx_t {
MppBufSlots frame_slots;
MppBufSlots packet_slots;
MppPacket task_pkt;
struct avsd_memory_t *mem; //!< resotre slice data to decoder
struct avsd_stream_buf_t *p_stream;
struct avsd_stream_buf_t *p_header;
//-------- input ---------------
RK_U32 frame_no;
ParserCfg init;
RK_U8 has_get_eos;
RK_U64 pkt_no;
//-------- current --------------
struct avsd_nalu_t *nal; //!< current nalu
//-------- video --------------
struct bitread_ctx_t bitctx;
RK_U8 got_eos;
RK_U32 pkt_no;
struct avsd_memory_t *mem;
RK_U8 *streambuf;
RK_U32 stream_len;
RK_U32 stream_size;
BitReadCtx_t *bx;
RK_U32 left_length;
AvsdSeqHeader_t vsh;
AvsdSeqExtHeader_t ext;
AvsdPicHeader_t ph;
AvsdSyntax_t *syn;
AvsdFrame_t *dpb[2]; //!< 2 refer frames or 4 refer field
AvsdFrame_t *cur; //!< for decoder field
//!<------------------------------------
RK_U32 need_split;
RK_U32 state;
RK_U32 vop_header_found;
RK_U32 got_vsh;
RK_U32 got_ph;
RK_U32 got_keyframe;
RK_U32 mb_width;
RK_U32 mb_height;
RK_U32 vec_flag; //!< video_edit_code_flag
RK_U32 disable_error;
} AvsdCtx_t;
@@ -269,7 +255,7 @@ MPP_RET avsd_fill_parameters(AvsdCtx_t *p_dec, AvsdSyntax_t *syn);
MPP_RET avsd_update_dpb(AvsdCtx_t *p_dec);
MPP_RET avsd_parse_prepare(AvsdCtx_t *p_dec, MppPacket *pkt, HalDecTask *task);
MPP_RET avsd_parser_split(AvsdCtx_t *ctx, MppPacket *dst, MppPacket *src);
MPP_RET avsd_parse_stream(AvsdCtx_t *p_dec, HalDecTask *task);
#ifdef __cplusplus

View File

@@ -23,6 +23,7 @@
extern "C" {
#endif
extern const ParserApi api_avsd_parser;
extern const ParserApi api_avsd_plus_parser;
MPP_RET avsd_init (void *decoder, ParserCfg *cfg);
MPP_RET avsd_deinit (void *decoder);

View File

@@ -45,6 +45,7 @@
static const ParserApi *parsers[] = {
#if HAVE_AVSD
&api_avsd_parser,
&api_avsd_plus_parser,
#endif
#if HAVE_AVS2D
&api_avs2d_parser,

View File

@@ -1,5 +1,4 @@
/*
*
* Copyright 2015 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,7 +14,6 @@
* limitations under the License.
*/
#ifndef __AVSD_SYNTAX_H__
#define __AVSD_SYNTAX_H__
@@ -92,6 +90,7 @@ typedef struct _PicParams_Avsd {
typedef struct avsd_syntax_t {
PicParams_Avsd pp;
RK_U8 *bitstream;
RK_U32 bitstream_offset;
RK_U32 bitstream_size;
} AvsdSyntax_t;

View File

@@ -1,5 +1,4 @@
/*
*
* Copyright 2015 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,7 +14,6 @@
* limitations under the License.
*/
#ifndef __HAL_AVSD_API_H__
#define __HAL_AVSD_API_H__
@@ -26,6 +24,7 @@ extern "C" {
#endif
extern const MppHalApi hal_api_avsd;
extern const MppHalApi hal_api_avsd_plus;
#ifdef __cplusplus
}

View File

@@ -46,6 +46,7 @@
static const MppHalApi *hw_apis[] = {
#if HAVE_AVSD
&hal_api_avsd,
&hal_api_avsd_plus,
#endif
#if HAVE_AVS2D
&hal_api_avs2d,

View File

@@ -6,13 +6,22 @@ set(HAL_AVSD_API
# hal avs header
set(HAL_AVSD_HDR
hal_avsd_reg.h
hal_avsd_base.h
hal_avsd_vdpu1.h
hal_avsd_vdpu2.h
hal_avsd_plus.h
hal_avsd_vdpu1_reg.h
hal_avsd_vdpu2_reg.h
hal_avsd_plus_reg.h
)
# hal avs decoder sourse
set(HAL_AVSD_SRC
hal_avsd_reg.c
hal_avsd_api.c
hal_avsd_base.c
hal_avsd_vdpu1.c
hal_avsd_vdpu2.c
hal_avsd_plus.c
)
add_library(hal_avsd STATIC

View File

@@ -1,5 +1,4 @@
/*
*
* Copyright 2015 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,142 +14,97 @@
* limitations under the License.
*/
#define MODULE_TAG "hal_avsd_api"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rk_mpi_cmd.h"
#include "mpp_debug.h"
#include "mpp_mem.h"
#include "mpp_env.h"
#include "mpp_common.h"
#include "mpp_platform.h"
#include "mpp_device.h"
#include "hal_avsd_api.h"
#include "hal_avsd_reg.h"
#include "mpp_dec_cb_param.h"
#include "hal_avsd_api.h"
#include "hal_avsd_base.h"
#include "hal_avsd_vdpu1.h"
#include "hal_avsd_vdpu2.h"
#include "hal_avsd_plus.h"
RK_U32 avsd_hal_debug = 0;
MPP_RET hal_avsd_start(void *decoder, HalTaskInfo *task);
MPP_RET hal_avsd_wait(void *decoder, HalTaskInfo *task);
static RK_U32 avsd_ver_align(RK_U32 val)
static MPP_RET init_hard_platform(AvsdHalCtx_t *p_hal, MppCodingType coding)
{
return MPP_ALIGN(val, 16);
}
static RK_U32 avsd_hor_align(RK_U32 val)
{
return MPP_ALIGN(val, 16);
}
static RK_U32 avsd_len_align(RK_U32 val)
{
return (2 * MPP_ALIGN(val, 16));
}
static void explain_input_buffer(AvsdHalCtx_t *p_hal, HalDecTask *task)
{
memcpy(&p_hal->syn, task->syntax.data, sizeof(AvsdSyntax_t));
}
static MPP_RET repeat_other_field(AvsdHalCtx_t *p_hal, HalTaskInfo *task)
{
RK_U8 i = 0;
RK_U8 *pdata = NULL;
MppBuffer mbuffer = NULL;
MppHalApi *p_api = &p_hal->hal_api;
RK_U32 vcodec_type = mpp_get_vcodec_type();
MppClientType client_type = VPU_CLIENT_BUTT;
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdRegs_t *p_regs = (AvsdRegs_t *)p_hal->p_regs;
//!< re-find start code and calculate offset
p_hal->data_offset = p_regs->sw12.rlc_vlc_base >> 10;
mpp_buf_slot_get_prop(p_hal->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer);
pdata = (RK_U8 *)mpp_buffer_get_ptr(mbuffer) + p_hal->data_offset;
while (i < 8) {
if (pdata[i] == 0 && pdata[i + 1] == 0 && pdata[i + 2] == 1) {
p_hal->data_offset += i;
p_hal->syn.bitstream_size -= i;
break;
if (coding == MPP_VIDEO_CodingAVSPLUS) {
if (!(vcodec_type & HAVE_AVSDEC))
mpp_err("coding %x vcodec_type %x do not found avs hw %x\n",
coding, vcodec_type, HAVE_AVSDEC);
} else {
RK_U32 hw_flag = HAVE_VDPU1 | HAVE_VDPU2 | HAVE_VDPU1_PP | HAVE_VDPU2_PP;
if (!(vcodec_type & hw_flag ))
mpp_err("coding %x vcodec_type %x do not found avs hw %x\n",
coding, vcodec_type, hw_flag);
}
i++;
if ((coding == MPP_VIDEO_CodingAVSPLUS) &&
(vcodec_type & HAVE_AVSDEC)) {
p_api->init = hal_avsd_plus_init;
p_api->deinit = hal_avsd_plus_deinit;
p_api->reg_gen = hal_avsd_plus_gen_regs;
p_api->start = hal_avsd_plus_start;
p_api->wait = hal_avsd_plus_wait;
p_api->reset = hal_avsd_plus_reset;
p_api->flush = hal_avsd_plus_flush;
p_api->control = hal_avsd_plus_control;
client_type = VPU_CLIENT_AVSPLUS_DEC;
} else if ((coding == MPP_VIDEO_CodingAVS) &&
(vcodec_type & (HAVE_VDPU1 | HAVE_VDPU1_PP))) {
p_api->init = hal_avsd_vdpu1_init;
p_api->deinit = hal_avsd_vdpu1_deinit;
p_api->reg_gen = hal_avsd_vdpu1_gen_regs;
p_api->start = hal_avsd_vdpu1_start;
p_api->wait = hal_avsd_vdpu1_wait;
p_api->reset = hal_avsd_vdpu1_reset;
p_api->flush = hal_avsd_vdpu1_flush;
p_api->control = hal_avsd_vdpu1_control;
client_type = VPU_CLIENT_VDPU1;
} else if ((coding == MPP_VIDEO_CodingAVS) &&
(vcodec_type & (HAVE_VDPU2 | HAVE_VDPU2_PP))) {
p_api->init = hal_avsd_vdpu2_init;
p_api->deinit = hal_avsd_vdpu2_deinit;
p_api->reg_gen = hal_avsd_vdpu2_gen_regs;
p_api->start = hal_avsd_vdpu2_start;
p_api->wait = hal_avsd_vdpu2_wait;
p_api->reset = hal_avsd_vdpu2_reset;
p_api->flush = hal_avsd_vdpu2_flush;
p_api->control = hal_avsd_vdpu2_control;
client_type = VPU_CLIENT_VDPU2;
} else {
ret = MPP_NOK;
goto __FAILED;
}
AVSD_HAL_DBG(AVSD_HAL_DBG_OFFSET, "frame_no=%d, offset=%d\n", p_hal->frame_no, p_hal->data_offset);
//!< re-generate register
memset(p_hal->p_regs, 0, sizeof(AvsdRegs_t));
FUN_CHECK(ret = set_defalut_parameters(p_hal));
FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec));
hal_avsd_start((void *)p_hal, task);
hal_avsd_wait((void *)p_hal, task);
p_hal->coding = coding;
AVSD_HAL_DBG(AVSD_DBG_HARD_MODE, "hw_spt %08x, coding %d\n", vcodec_type, coding);
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief
* init
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_init(void *decoder, MppHalCfg *cfg)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = NULL;
AVSD_HAL_TRACE("In.");
INP_CHECK(ret, NULL == decoder);
mpp_env_get_u32("avsd_debug", &avsd_hal_debug, 0);
p_hal = (AvsdHalCtx_t *)decoder;
memset(p_hal, 0, sizeof(AvsdHalCtx_t));
p_hal->frame_slots = cfg->frame_slots;
p_hal->packet_slots = cfg->packet_slots;
//!< callback function to parser module
p_hal->dec_cb = cfg->dec_cb;
//!< mpp_device_init
ret = mpp_dev_init(&p_hal->dev, VPU_CLIENT_AVSPLUS_DEC);
ret = mpp_dev_init(&p_hal->dev, client_type);
if (ret) {
mpp_err("mpp_device_init failed. ret: %d\n", ret);
return ret;
}
//< get buffer group
if (p_hal->buf_group == NULL) {
RK_U32 buf_size = (1920 * 1088) / 16;
FUN_CHECK(ret = mpp_buffer_group_get_internal(&p_hal->buf_group, MPP_BUFFER_TYPE_ION));
FUN_CHECK(ret = mpp_buffer_get(p_hal->buf_group, &p_hal->mv_buf, buf_size));
}
mpp_slots_set_prop(p_hal->frame_slots, SLOTS_HOR_ALIGN, avsd_hor_align);
mpp_slots_set_prop(p_hal->frame_slots, SLOTS_VER_ALIGN, avsd_ver_align);
mpp_slots_set_prop(p_hal->frame_slots, SLOTS_LEN_ALIGN, avsd_len_align);
p_hal->p_regs = mpp_calloc_size(RK_U32 , sizeof(AvsdRegs_t));
MEM_CHECK(ret, p_hal->p_regs);
//!< initial for control
p_hal->first_field = 1;
p_hal->prev_pic_structure = 0; //!< field
memset(p_hal->pic, 0, sizeof(p_hal->pic));
p_hal->work_out = -1;
p_hal->work0 = -1;
p_hal->work1 = -1;
__RETURN:
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief
@@ -166,20 +120,17 @@ MPP_RET hal_avsd_deinit(void *decoder)
AVSD_HAL_TRACE("In.");
INP_CHECK(ret, NULL == decoder);
//!< mpp_device_init
FUN_CHECK(ret = p_hal->hal_api.deinit(decoder));
//!< mpp_dev_init
if (p_hal->dev) {
ret = mpp_dev_deinit(p_hal->dev);
if (ret)
mpp_err("mpp_dev_deinit failed. ret: %d\n", ret);
}
if (p_hal->mv_buf) {
FUN_CHECK(ret = mpp_buffer_put(p_hal->mv_buf));
}
if (p_hal->buf_group) {
FUN_CHECK(ret = mpp_buffer_group_put(p_hal->buf_group));
}
MPP_FREE(p_hal->p_regs);
__RETURN:
AVSD_HAL_TRACE("Out.");
@@ -187,6 +138,46 @@ __RETURN:
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief
* init
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_init(void *decoder, MppHalCfg *cfg)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
INP_CHECK(ret, NULL == decoder);
memset(p_hal, 0, sizeof(AvsdHalCtx_t));
p_hal->frame_slots = cfg->frame_slots;
p_hal->packet_slots = cfg->packet_slots;
//!< callback function to parser module
p_hal->dec_cb = cfg->dec_cb;
mpp_env_get_u32("avsd_debug", &avsd_hal_debug, 0);
//< get buffer group
FUN_CHECK(ret = mpp_buffer_group_get_internal(&p_hal->buf_group, MPP_BUFFER_TYPE_ION));
FUN_CHECK(ret = init_hard_platform(p_hal, cfg->coding));
//!< run init funtion
FUN_CHECK(ret = p_hal->hal_api.init(decoder, cfg));
__RETURN:
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
__FAILED:
hal_avsd_deinit(decoder);
return ret;
}
/*!
***********************************************************************
* \brief
@@ -197,28 +188,31 @@ __FAILED:
MPP_RET hal_avsd_gen_regs(void *decoder, HalTaskInfo *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
MppCodingType coding = MPP_VIDEO_CodingUnused;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
INP_CHECK(ret, NULL == decoder);
if (task->dec.flags.parse_err ||
task->dec.flags.ref_err) {
goto __RETURN;
memcpy(&p_hal->syn, task->dec.syntax.data, sizeof(AvsdSyntax_t));
// check coding
coding = (p_hal->syn.pp.profileId == 0x48) ? MPP_VIDEO_CodingAVSPLUS : MPP_VIDEO_CodingAVS;
if (coding != p_hal->coding) {
if (p_hal->dev) {
ret = mpp_dev_deinit(p_hal->dev);
if (ret)
mpp_err("mpp_dev_deinit failed. ret: %d\n", ret);
p_hal->dev = NULL;
}
memset(p_hal->p_regs, 0, sizeof(AvsdRegs_t));
explain_input_buffer(p_hal, &task->dec);
p_hal->data_offset = 0;
FUN_CHECK(ret = set_defalut_parameters(p_hal));
FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec));
__RETURN:
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
__FAILED:
ret = init_hard_platform(p_hal, coding);
if (ret) {
mpp_err_f("change paltform %x -> %x error\n", p_hal->coding, coding);
return ret;
}
}
p_hal->frame_no++;
return p_hal->hal_api.reg_gen(decoder, task);
}
/*!
***********************************************************************
* \brief h
@@ -228,53 +222,9 @@ __FAILED:
//extern "C"
MPP_RET hal_avsd_start(void *decoder, HalTaskInfo *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
INP_CHECK(ret, NULL == decoder);
if (task->dec.flags.parse_err || task->dec.flags.ref_err) {
goto __RETURN;
}
do {
MppDevRegWrCfg wr_cfg;
MppDevRegRdCfg rd_cfg;
wr_cfg.reg = p_hal->p_regs;
wr_cfg.size = AVSD_REGISTERS * sizeof(RK_U32);
wr_cfg.offset = 0;
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_REG_WR, &wr_cfg);
if (ret) {
mpp_err_f("set register write failed %d\n", ret);
break;
}
rd_cfg.reg = p_hal->p_regs;
rd_cfg.size = AVSD_REGISTERS * sizeof(RK_U32);
rd_cfg.offset = 0;
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_REG_RD, &rd_cfg);
if (ret) {
mpp_err_f("set register read failed %d\n", ret);
break;
}
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_CMD_SEND, NULL);
if (ret) {
mpp_err_f("send cmd failed %d\n", ret);
break;
}
} while (0);
p_hal->frame_no++;
__RETURN:
AVSD_HAL_TRACE("Out.");
return ret;
return p_hal->hal_api.start(decoder, task);
}
/*!
***********************************************************************
@@ -285,42 +235,9 @@ __RETURN:
//extern "C"
MPP_RET hal_avsd_wait(void *decoder, HalTaskInfo *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AvsdRegs_t *p_regs = (AvsdRegs_t *)p_hal->p_regs;
AVSD_HAL_TRACE("In.");
INP_CHECK(ret, NULL == decoder);
if (task->dec.flags.parse_err ||
task->dec.flags.ref_err) {
goto __SKIP_HARD;
}
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_CMD_POLL, NULL);
if (ret)
mpp_err_f("poll cmd failed %d\n", ret);
update_parameters(p_hal);
if (!p_hal->first_field && p_hal->syn.pp.pictureStructure == FIELDPICTURE)
repeat_other_field(p_hal, task);
__SKIP_HARD:
if (p_hal->dec_cb) {
DecCbHalDone param;
param.task = (void *)&task->dec;
param.regs = (RK_U32 *)p_regs;
param.hard_err = !p_regs->sw01.dec_rdy_int;
mpp_callback(p_hal->dec_cb, &param);
}
memset(&p_regs->sw01, 0, sizeof(p_regs->sw01));
__RETURN:
AVSD_HAL_TRACE("Out.");
return ret;
return p_hal->hal_api.wait(decoder, task);
}
/*!
***********************************************************************
@@ -331,29 +248,55 @@ __RETURN:
//extern "C"
MPP_RET hal_avsd_reset(void *decoder)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
return p_hal->hal_api.reset(p_hal);
}
/*!
***********************************************************************
* \brief
* flush
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_flush(void *decoder)
{
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
memset(p_hal->p_regs, 0, sizeof(AvsdRegs_t));
return p_hal->hal_api.flush(p_hal);
}
/*!
***********************************************************************
* \brief
* control
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_control(void *decoder, MpiCmd cmd_type, void *param)
{
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
p_hal->first_field = 1;
p_hal->prev_pic_structure = 0; //!< field
memset(p_hal->pic, 0, sizeof(p_hal->pic));
p_hal->work_out = -1;
p_hal->work0 = -1;
p_hal->work1 = -1;
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
return p_hal->hal_api.control(decoder, cmd_type, param);
}
const MppHalApi hal_api_avsd = {
.name = "avsd_rkdec",
.name = "avsd_vdpu",
.type = MPP_CTX_DEC,
.coding = MPP_VIDEO_CodingAVS,
.ctx_size = sizeof(AvsdHalCtx_t),
.flag = 0,
.init = hal_avsd_init,
.deinit = hal_avsd_deinit,
.reg_gen = hal_avsd_gen_regs,
.start = hal_avsd_start,
.wait = hal_avsd_wait,
.reset = hal_avsd_reset,
.flush = hal_avsd_flush,
.control = hal_avsd_control,
};
const MppHalApi hal_api_avsd_plus = {
.name = "avsd_plus",
.type = MPP_CTX_DEC,
.coding = MPP_VIDEO_CodingAVSPLUS,
.ctx_size = sizeof(AvsdHalCtx_t),
@@ -364,6 +307,6 @@ const MppHalApi hal_api_avsd = {
.start = hal_avsd_start,
.wait = hal_avsd_wait,
.reset = hal_avsd_reset,
.flush = NULL,
.control = NULL,
.flush = hal_avsd_flush,
.control = hal_avsd_control,
};

View File

@@ -0,0 +1,80 @@
/*
* 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_avsd_base"
#include <assert.h>
#include "mpp_log.h"
#include "mpp_common.h"
#include "hal_avsd_base.h"
RK_U32 avsd_hal_debug = 0;
RK_U32 avsd_ver_align(RK_U32 val)
{
return MPP_ALIGN(val, 16);
}
RK_U32 avsd_hor_align(RK_U32 val)
{
return MPP_ALIGN(val, 16);
}
RK_U32 avsd_len_align(RK_U32 val)
{
return (2 * MPP_ALIGN(val, 16));
}
RK_S32 get_queue_pic(AvsdHalCtx_t *p_hal)
{
RK_U32 i = 0;
RK_S32 ret_idx = -1;
for (i = 0; i < MPP_ARRAY_ELEMS(p_hal->pic); i++) {
if (!p_hal->pic[i].valid) {
ret_idx = i;
p_hal->pic[i].valid = 1;
break;
}
}
return ret_idx;
}
RK_S32 get_packet_fd(AvsdHalCtx_t *p_hal, RK_S32 idx)
{
RK_S32 ret_fd = 0;
MppBuffer mbuffer = NULL;
mpp_buf_slot_get_prop(p_hal->packet_slots, idx, SLOT_BUFFER, &mbuffer);
assert(mbuffer);
ret_fd = mpp_buffer_get_fd(mbuffer);
return ret_fd;
}
RK_S32 get_frame_fd(AvsdHalCtx_t *p_hal, RK_S32 idx)
{
RK_S32 ret_fd = 0;
MppBuffer mbuffer = NULL;
mpp_buf_slot_get_prop(p_hal->frame_slots, idx, SLOT_BUFFER, &mbuffer);
assert(mbuffer);
ret_fd = mpp_buffer_get_fd(mbuffer);
return ret_fd;
}

View File

@@ -0,0 +1,146 @@
/*
* 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_AVSD_BASE_H__
#define __HAL_AVSD_BASE_H__
#include "parser_api.h"
#include "hal_avsd_api.h"
#include "avsd_syntax.h"
#include "mpp_device.h"
#define AVSD_HAL_DBG_ERROR (0x00000001)
#define AVSD_HAL_DBG_ASSERT (0x00000002)
#define AVSD_HAL_DBG_WARNNING (0x00000004)
#define AVSD_HAL_DBG_TRACE (0x00000008)
#define AVSD_HAL_DBG_OFFSET (0x00000010)
#define AVSD_HAL_DBG_WAIT (0x00000020)
#define AVSD_DBG_HARD_MODE (0x00010000)
#define AVSD_DBG_PROFILE_ID (0x00020000)
extern RK_U32 avsd_hal_debug;
#define AVSD_HAL_DBG(level, fmt, ...)\
do {\
if (level & avsd_hal_debug)\
{ mpp_log(fmt, ## __VA_ARGS__); }\
} while (0)
#define AVSD_HAL_TRACE(fmt, ...)\
do {\
if (AVSD_HAL_DBG_TRACE & avsd_hal_debug)\
{ mpp_log_f(fmt, ## __VA_ARGS__); }\
} while (0)
#define INP_CHECK(ret, val, ...)\
do{\
if ((val)) { \
ret = MPP_ERR_INIT; \
AVSD_HAL_DBG(AVSD_HAL_DBG_WARNNING, "input empty(%d).\n", __LINE__); \
goto __RETURN; \
}\
} while (0)
#define FUN_CHECK(val)\
do{\
if ((val) < 0) {\
AVSD_HAL_DBG(AVSD_HAL_DBG_WARNNING, "Function error(%d).\n", __LINE__); \
goto __FAILED; \
}\
} while (0)
//!< memory malloc check
#define MEM_CHECK(ret, val, ...)\
do{\
if (!(val)) {\
ret = MPP_ERR_MALLOC; \
mpp_err_f("malloc buffer error(%d).\n", __LINE__); \
goto __FAILED; \
}\
} while (0)
#define FIELDPICTURE 0
#define FRAMEPICTURE 1
enum {
IFRAME = 0,
PFRAME = 1,
BFRAME = 2
};
typedef struct avsd_hal_picture_t {
RK_U32 valid;
RK_U32 pic_type;
RK_U32 pic_code_type;
RK_U32 picture_distance;
RK_S32 slot_idx;
} AvsdHalPic_t;
typedef struct avsd_hal_ctx_t {
MppHalApi hal_api;
MppBufSlots frame_slots;
MppBufSlots packet_slots;
MppBufferGroup buf_group;
MppCodingType coding;
MppCbCtx *dec_cb;
MppDev dev;
AvsdSyntax_t syn;
RK_U32 *p_regs;
RK_U32 regs_num;
MppBuffer mv_buf;
AvsdHalPic_t pic[3];
//!< add for control
RK_U32 first_field;
RK_U32 prev_pic_structure;
RK_U32 prev_pic_code_type;
RK_S32 future2prev_past_dist;
RK_S32 work0;
RK_S32 work1;
RK_S32 work_out;
RK_U32 data_offset;
RK_U32 frame_no;
} AvsdHalCtx_t;
#ifdef __cplusplus
extern "C" {
#endif
RK_U32 avsd_ver_align(RK_U32 val);
RK_U32 avsd_hor_align(RK_U32 val);
RK_U32 avsd_len_align(RK_U32 val);
RK_S32 get_queue_pic(AvsdHalCtx_t *p_hal);
RK_S32 get_packet_fd(AvsdHalCtx_t *p_hal, RK_S32 idx);
RK_S32 get_frame_fd(AvsdHalCtx_t *p_hal, RK_S32 idx);
#ifdef __cplusplus
}
#endif
#endif /*__HAL_AVSD_COMMON_H__*/

View File

@@ -1,5 +1,4 @@
/*
*
* Copyright 2015 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,51 +14,21 @@
* limitations under the License.
*/
#define MODULE_TAG "hal_avsd_reg"
#define MODULE_TAG "hal_avsd_plus"
#include <string.h>
#include "mpp_common.h"
#include "mpp_mem.h"
#include "mpp_device.h"
#include "avsd_syntax.h"
#include "hal_avsd_api.h"
#include "hal_avsd_reg.h"
#include "hal_avsd_plus_reg.h"
#include "hal_avsd_plus.h"
#include "mpp_dec_cb_param.h"
#include "hal_avsd_base.h"
static RK_S32 get_queue_pic(AvsdHalCtx_t *p_hal)
{
RK_U32 i = 0;
RK_S32 ret_idx = -1;
for (i = 0; i < MPP_ARRAY_ELEMS(p_hal->pic); i++) {
if (!p_hal->pic[i].valid) {
ret_idx = i;
p_hal->pic[i].valid = 1;
break;
}
}
return ret_idx;
}
static RK_S32 get_packet_fd(AvsdHalCtx_t *p_hal, RK_S32 idx)
{
RK_S32 ret_fd = 0;
MppBuffer mbuffer = NULL;
mpp_buf_slot_get_prop(p_hal->packet_slots, idx, SLOT_BUFFER, &mbuffer);
ret_fd = mpp_buffer_get_fd(mbuffer);
return ret_fd;
}
static RK_S32 get_frame_fd(AvsdHalCtx_t *p_hal, RK_S32 idx)
{
RK_S32 ret_fd = 0;
MppBuffer mbuffer = NULL;
mpp_buf_slot_get_prop(p_hal->frame_slots, idx, SLOT_BUFFER, &mbuffer);
ret_fd = mpp_buffer_get_fd(mbuffer);
return ret_fd;
}
/*!
***********************************************************************
* \brief
@@ -69,7 +38,7 @@ static RK_S32 get_frame_fd(AvsdHalCtx_t *p_hal, RK_S32 idx)
//extern "C"
MPP_RET set_defalut_parameters(AvsdHalCtx_t *p_hal)
{
AvsdRegs_t *p_regs = (AvsdRegs_t *)p_hal->p_regs;
AvsdPlusRegs_t *p_regs = (AvsdPlusRegs_t *)p_hal->p_regs;
p_regs->sw02.dec_out_endian = 1;
p_regs->sw02.dec_in_endian = 0;
@@ -107,19 +76,12 @@ MPP_RET set_defalut_parameters(AvsdHalCtx_t *p_hal)
return MPP_OK;
}
/*!
***********************************************************************
* \brief
* generate register parameters
***********************************************************************
*/
//extern "C"
MPP_RET set_regs_parameters(AvsdHalCtx_t *p_hal, HalDecTask *task)
static MPP_RET set_regs_parameters(AvsdHalCtx_t *p_hal, HalDecTask *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdSyntax_t *p_syn = &p_hal->syn;
AvsdRegs_t *p_regs = (AvsdRegs_t *)p_hal->p_regs;
AvsdPlusRegs_t *p_regs = (AvsdPlusRegs_t *)p_hal->p_regs;
//!< set wrok_out pic info
if (p_hal->work_out < 0) {
@@ -138,6 +100,7 @@ MPP_RET set_regs_parameters(AvsdHalCtx_t *p_hal, HalDecTask *task)
p_work_out->picture_distance = p_syn->pp.pictureDistance;
}
//!< set register
set_defalut_parameters(p_hal);
p_regs->sw04.pic_mb_width = (p_syn->pp.horizontalSize + 15) >> 4;
p_regs->sw03.dec_mode = 11; //!< DEC_MODE_AVS
@@ -156,7 +119,7 @@ MPP_RET set_regs_parameters(AvsdHalCtx_t *p_hal, HalDecTask *task)
}
p_regs->sw04.pic_mb_height_p = (p_syn->pp.verticalSize + 15) >> 4;
p_regs->sw07.avs_h264_h_ext = (p_syn->pp.verticalSize + 15) >> 12;
p_regs->sw07.avs_h_ext = (p_syn->pp.verticalSize + 15) >> 12;
if (p_syn->pp.picCodingType == BFRAME) {
p_regs->sw03.pic_b_e = 1;
@@ -169,6 +132,7 @@ MPP_RET set_regs_parameters(AvsdHalCtx_t *p_hal, HalDecTask *task)
p_hal->data_offset = (p_hal->data_offset & ~0x7);
p_regs->sw12.rlc_vlc_base = get_packet_fd(p_hal, task->input) | (p_hal->data_offset << 10);
p_regs->sw06.stream_len = p_syn->bitstream_size - p_hal->data_offset;
p_regs->sw03.pic_fixed_quant = p_syn->pp.fixedPictureQp;
p_regs->sw06.init_qp = p_syn->pp.pictureQp;
//!< AVS Plus stuff
@@ -492,8 +456,13 @@ MPP_RET set_regs_parameters(AvsdHalCtx_t *p_hal, HalDecTask *task)
(p_syn->pp.picCodingType == BFRAME && p_hal->prev_pic_structure)) {
p_regs->sw41.dir_mv_base = mpp_buffer_get_fd(p_hal->mv_buf);
} else {
RK_U32 offset = MPP_ALIGN(p_syn->pp.horizontalSize, 16)
* MPP_ALIGN(p_syn->pp.verticalSize, 16) / 32;
RK_U32 frame_width = 0, frame_height = 0, offset = 0;
frame_width = (p_syn->pp.horizontalSize + 15) >> 4;
if (p_syn->pp.progressiveFrame)
frame_height = (p_syn->pp.verticalSize + 15) >> 4;
else
frame_height = 2 * ((p_syn->pp.verticalSize + 31) >> 5);
offset = MPP_ALIGN(frame_width * frame_height / 2, 2) * 16;
p_regs->sw41.dir_mv_base = mpp_buffer_get_fd(p_hal->mv_buf) | (offset << 10);
}
//!< AVS Plus stuff
@@ -522,14 +491,7 @@ __FAILED:
return ret;
}
/*!
***********************************************************************
* \brief
* init decoder parameters
***********************************************************************
*/
//extern "C"
MPP_RET update_parameters(AvsdHalCtx_t *p_hal)
static MPP_RET update_parameters(AvsdHalCtx_t *p_hal)
{
AvsdSyntax_t *p_syn = &p_hal->syn;
@@ -552,3 +514,295 @@ MPP_RET update_parameters(AvsdHalCtx_t *p_hal)
return MPP_OK;
}
static MPP_RET repeat_other_field(AvsdHalCtx_t *p_hal, HalTaskInfo *task)
{
RK_U8 i = 0;
RK_U8 *pdata = NULL;
MppBuffer mbuffer = NULL;
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdPlusRegs_t *p_regs = (AvsdPlusRegs_t *)p_hal->p_regs;
//!< re-find start code and calculate offset
p_hal->data_offset = p_regs->sw12.rlc_vlc_base >> 10;
p_hal->data_offset += p_hal->syn.bitstream_offset;
p_hal->data_offset -= MPP_MIN(p_hal->data_offset, 8);
mpp_buf_slot_get_prop(p_hal->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer);
pdata = (RK_U8 *)mpp_buffer_get_ptr(mbuffer) + p_hal->data_offset;
while (i < 16) {
if (pdata[i] == 0 && pdata[i + 1] == 0 && pdata[i + 2] == 1) {
p_hal->data_offset += i;
break;
}
i++;
}
AVSD_HAL_DBG(AVSD_HAL_DBG_OFFSET, "frame_no=%d, i=%d, offset=%d\n",
p_hal->frame_no, i, p_hal->data_offset);
//!< re-generate register
FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec));
hal_avsd_plus_start((void *)p_hal, task);
hal_avsd_plus_wait((void *)p_hal, task);
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief
* init
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_plus_init(void *decoder, MppHalCfg *cfg)
{
MPP_RET ret = MPP_ERR_UNKNOW;
RK_U32 buf_size = 0;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("AVS_plus In.");
buf_size = (1920 * 1088) * 2;
FUN_CHECK(ret = mpp_buffer_get(p_hal->buf_group, &p_hal->mv_buf, buf_size));
p_hal->p_regs = mpp_calloc_size(RK_U32, sizeof(AvsdPlusRegs_t));
MEM_CHECK(ret, p_hal->p_regs);
mpp_slots_set_prop(p_hal->frame_slots, SLOTS_HOR_ALIGN, avsd_hor_align);
mpp_slots_set_prop(p_hal->frame_slots, SLOTS_VER_ALIGN, avsd_ver_align);
mpp_slots_set_prop(p_hal->frame_slots, SLOTS_LEN_ALIGN, avsd_len_align);
p_hal->regs_num = 60;
//!< initial for control
p_hal->first_field = 1;
p_hal->prev_pic_structure = 0; //!< field
memset(p_hal->pic, 0, sizeof(p_hal->pic));
p_hal->work_out = -1;
p_hal->work0 = -1;
p_hal->work1 = -1;
AVSD_HAL_TRACE("Out.");
(void)cfg;
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief
* deinit
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_plus_deinit(void *decoder)
{
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
if (p_hal->mv_buf) {
mpp_buffer_put(p_hal->mv_buf);
p_hal->mv_buf = NULL;
}
MPP_FREE(p_hal->p_regs);
AVSD_HAL_TRACE("Out.");
return MPP_OK;
}
/*!
***********************************************************************
* \brief
* generate register
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_plus_gen_regs(void *decoder, HalTaskInfo *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
if (task->dec.flags.parse_err || task->dec.flags.ref_err) {
goto __RETURN;
}
p_hal->data_offset = p_hal->syn.bitstream_offset;
FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec));
__RETURN:
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief h
* start hard
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_plus_start(void *decoder, HalTaskInfo *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
INP_CHECK(ret, NULL == decoder);
if (task->dec.flags.parse_err || task->dec.flags.ref_err) {
goto __RETURN;
}
do {
MppDevRegWrCfg wr_cfg;
MppDevRegRdCfg rd_cfg;
wr_cfg.reg = p_hal->p_regs;
wr_cfg.size = AVSD_REGISTERS * sizeof(RK_U32);
wr_cfg.offset = 0;
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_REG_WR, &wr_cfg);
if (ret) {
mpp_err_f("set register write failed %d\n", ret);
break;
}
rd_cfg.reg = p_hal->p_regs;
rd_cfg.size = AVSD_REGISTERS * sizeof(RK_U32);
rd_cfg.offset = 0;
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_REG_RD, &rd_cfg);
if (ret) {
mpp_err_f("set register read failed %d\n", ret);
break;
}
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_CMD_SEND, NULL);
if (ret) {
mpp_err_f("send cmd failed %d\n", ret);
break;
}
} while (0);
p_hal->frame_no++;
__RETURN:
AVSD_HAL_TRACE("Out.");
return ret;
}
/*!
***********************************************************************
* \brief
* wait hard
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_plus_wait(void *decoder, HalTaskInfo *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
INP_CHECK(ret, NULL == decoder);
if (task->dec.flags.parse_err ||
task->dec.flags.ref_err) {
goto __SKIP_HARD;
}
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_CMD_POLL, NULL);
if (ret)
mpp_err_f("poll cmd failed %d\n", ret);
__SKIP_HARD:
if (p_hal->dec_cb) {
DecCbHalDone param;
param.task = (void *)&task->dec;
param.regs = (RK_U32 *)p_hal->p_regs;
param.hard_err = (!((AvsdPlusRegs_t *)p_hal->p_regs)->sw01.dec_rdy_int);
mpp_callback(p_hal->dec_cb, &param);
}
update_parameters(p_hal);
memset(&p_hal->p_regs[1], 0, sizeof(RK_U32));
if (!p_hal->first_field && p_hal->syn.pp.pictureStructure == FIELDPICTURE &&
!task->dec.flags.parse_err && !task->dec.flags.ref_err) {
repeat_other_field(p_hal, task);
}
__RETURN:
AVSD_HAL_TRACE("Out.");
return ret;
}
/*!
***********************************************************************
* \brief
* reset
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_plus_reset(void *decoder)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
p_hal->first_field = 1;
p_hal->prev_pic_structure = 0; //!< field
memset(p_hal->pic, 0, sizeof(p_hal->pic));
p_hal->work_out = -1;
p_hal->work0 = -1;
p_hal->work1 = -1;
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}
/*!
***********************************************************************
* \brief
* flush
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_plus_flush(void *decoder)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AVSD_HAL_TRACE("In.");
(void)decoder;
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}
/*!
***********************************************************************
* \brief
* control
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_plus_control(void *decoder, MpiCmd cmd_type, void *param)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AVSD_HAL_TRACE("In.");
(void)decoder;
(void)cmd_type;
(void)param;
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}

View File

@@ -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_AVSD_PLUS_H__
#define __HAL_AVSD_PLUS_H__
#ifdef __cplusplus
extern "C" {
#endif
MPP_RET hal_avsd_plus_init (void *decoder, MppHalCfg *cfg);
MPP_RET hal_avsd_plus_deinit (void *decoder);
MPP_RET hal_avsd_plus_gen_regs(void *decoder, HalTaskInfo *task);
MPP_RET hal_avsd_plus_start (void *decoder, HalTaskInfo *task);
MPP_RET hal_avsd_plus_wait (void *decoder, HalTaskInfo *task);
MPP_RET hal_avsd_plus_reset (void *decoder);
MPP_RET hal_avsd_plus_flush (void *decoder);
MPP_RET hal_avsd_plus_control (void *decoder, MpiCmd cmd_type, void *param);
#ifdef __cplusplus
}
#endif
#endif /*__HAL_AVSD_PLUS_H__*/

View File

@@ -24,96 +24,6 @@
#include "hal_avsd_api.h"
#include "avsd_syntax.h"
#define AVSD_HAL_DBG_ERROR (0x00000001)
#define AVSD_HAL_DBG_ASSERT (0x00000002)
#define AVSD_HAL_DBG_WARNNING (0x00000004)
#define AVSD_HAL_DBG_TRACE (0x00000008)
#define AVSD_HAL_DBG_OFFSET (0x00010000)
extern RK_U32 avsd_hal_debug;
#define AVSD_HAL_DBG(level, fmt, ...)\
do {\
if (level & avsd_hal_debug)\
{ mpp_log(fmt, ## __VA_ARGS__); }\
} while (0)
#define AVSD_HAL_TRACE(fmt, ...)\
do {\
if (AVSD_HAL_DBG_TRACE & avsd_hal_debug)\
{ mpp_log_f(fmt, ## __VA_ARGS__); }\
} while (0)
#define INP_CHECK(ret, val, ...)\
do{\
if ((val)) { \
ret = MPP_ERR_INIT; \
AVSD_HAL_DBG(AVSD_HAL_DBG_WARNNING, "input empty(%d).\n", __LINE__); \
goto __RETURN; \
}\
} while (0)
#define FUN_CHECK(val)\
do{\
if ((val) < 0) {\
AVSD_HAL_DBG(AVSD_HAL_DBG_WARNNING, "Function error(%d).\n", __LINE__); \
goto __FAILED; \
}\
} while (0)
//!< memory malloc check
#define MEM_CHECK(ret, val, ...)\
do{\
if (!(val)) {\
ret = MPP_ERR_MALLOC; \
mpp_err_f("malloc buffer error(%d).\n", __LINE__); \
goto __FAILED; \
}\
} while (0)
#define FIELDPICTURE 0
#define FRAMEPICTURE 1
enum {
IFRAME = 0,
PFRAME = 1,
BFRAME = 2
};
typedef struct avsd_hal_picture_t {
RK_U32 valid;
RK_U32 pic_type;
RK_U32 pic_code_type;
RK_U32 picture_distance;
RK_S32 slot_idx;
} AvsdHalPic_t;
typedef struct avsd_hal_ctx_t {
MppBufSlots frame_slots;
MppBufSlots packet_slots;
MppBufferGroup buf_group;
MppCbCtx *dec_cb;
MppDev dev;
AvsdSyntax_t syn;
RK_U32 *p_regs;
MppBuffer mv_buf;
AvsdHalPic_t pic[3];
//!< add for control
RK_U32 first_field;
RK_U32 prev_pic_structure;
RK_U32 prev_pic_code_type;
RK_S32 future2prev_past_dist;
RK_S32 work0;
RK_S32 work1;
RK_S32 work_out;
RK_U32 data_offset;
RK_U32 frame_no;
} AvsdHalCtx_t;
#define AVSD_REGISTERS 60
typedef struct {
@@ -130,13 +40,13 @@ typedef struct {
RK_U32 dec_rdy_int : 1;
RK_U32 dec_bus_int : 1;
RK_U32 dec_buffer_int : 1;
RK_U32 dec_aso_int : 1;
RK_U32 reserve3 : 1;
RK_U32 dec_error_int : 1;
RK_U32 dec_slice_int : 1;
RK_U32 reserve4 : 1;
RK_U32 dec_timeout : 1;
RK_U32 reserve3 : 5;
RK_U32 reserve5 : 5;
RK_U32 dec_pic_inf : 1;
RK_U32 reserve4 : 7;
RK_U32 reserve6 : 7;
} sw01;
union {
struct {
@@ -170,22 +80,21 @@ typedef struct {
RK_U32 dec_axi_wr_id : 8;
RK_U32 dec_ahb_hlock_e : 1;
RK_U32 picord_count_e : 1;
RK_U32 seq_mbaff_e : 1;
RK_U32 reserve0 : 1;
RK_U32 reftopfirst_e : 1;
RK_U32 write_mvs_e : 1;
RK_U32 pic_fixed_quant : 1;
RK_U32 filtering_dis : 1;
RK_U32 dec_out_dis : 1;
RK_U32 ref_topfield_e : 1;
RK_U32 sorenson_e : 1;
RK_U32 reserve1 : 1;
RK_U32 fwd_interlace_e : 1;
RK_U32 pic_topfiled_e : 1;
RK_U32 pic_inter_e : 1;
RK_U32 pic_b_e : 1;
RK_U32 pic_fieldmode_e : 1;
RK_U32 pic_interlace_e : 1;
RK_U32 pjpeg_e : 1;
RK_U32 divx3_e : 1;
RK_U32 reserve2 : 2;
RK_U32 skip_mode : 1;
RK_U32 rlc_mode_e : 1;
RK_U32 dec_mode : 4;
@@ -209,7 +118,6 @@ typedef struct {
RK_U32 strm_start_bit : 6;
};
} sw05;
struct {
RK_U32 stream_len : 24;
RK_U32 stream_len_ext : 1;
@@ -218,7 +126,7 @@ typedef struct {
} sw06;
struct {
RK_U32 reserve0 : 25;
RK_U32 avs_h264_h_ext : 1;
RK_U32 avs_h_ext : 1;
RK_U32 reserve1 : 6;
} sw07;
RK_U32 sw08;
@@ -301,7 +209,6 @@ typedef struct {
RK_U32 ref_dist_cur_2 : 16;
RK_U32 ref_dist_cur_3 : 16;
} sw31;
struct {
RK_U32 ref_invd_col_0 : 16;
RK_U32 ref_invd_col_1 : 16;
@@ -399,27 +306,13 @@ typedef struct {
struct {
RK_U32 refbu_bot_sum : 16;
RK_U32 refbu_top_sum : 16;
};
} sw56;
RK_U32 sw57;
struct {
RK_U32 reserve0 : 31;
RK_U32 serv_merge_dis : 1;
} sw58;
RK_U32 sw59;
} AvsdRegs_t;
} AvsdPlusRegs_t;
#ifdef __cplusplus
extern "C" {
#endif
MPP_RET set_defalut_parameters(AvsdHalCtx_t *p_hal);
MPP_RET set_regs_parameters(AvsdHalCtx_t *p_hal, HalDecTask *task);
MPP_RET update_parameters(AvsdHalCtx_t *p_hal);
#ifdef __cplusplus
}
#endif
#endif /*__HAL_AVSD_REG_H__*/
#endif /*__HAL_AVSD_PLUS_REG_H__*/

View File

@@ -0,0 +1,728 @@
/*
* 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_avsd_vdpu1"
#include <string.h>
#include "mpp_debug.h"
#include "mpp_common.h"
#include "mpp_mem.h"
#include "mpp_device.h"
#include "mpp_dec_cb_param.h"
#include "hal_avsd_base.h"
#include "hal_avsd_vdpu1.h"
#include "hal_avsd_vdpu1_reg.h"
static MPP_RET set_defalut_parameters(AvsdHalCtx_t *p_hal)
{
AvsdVdpu1Regs_t *p_regs = (AvsdVdpu1Regs_t *)p_hal->p_regs;
p_regs->sw02.dec_out_endian = 1;
p_regs->sw02.dec_in_endian = 0;
p_regs->sw02.dec_strendian_e = 1;
p_regs->sw02.dec_max_burst = 16;
p_regs->sw02.dec_scmd_dis = 0;
p_regs->sw02.dec_adv_pre_dis = 0;
p_regs->sw55.apf_threshold = 8;
p_regs->sw02.dec_latency = 0;
p_regs->sw02.dec_data_disc_e = 0;
p_regs->sw02.dec_outswap32_e = 1;
p_regs->sw02.dec_inswap32_e = 1;
p_regs->sw02.dec_strswap32_e = 1;
p_regs->sw02.dec_timeout_e = 0;
p_regs->sw02.dec_clk_gate_e = 1;
p_regs->sw01.dec_irq_dis = 0;
p_regs->sw02.dec_axi_rd_id = 0xFF;
p_regs->sw03.dec_axi_wr_id = 0;
p_regs->sw49.pred_bc_tap_0_0 = 0x3FF;
p_regs->sw49.pred_bc_tap_0_1 = 5;
p_regs->sw49.pred_bc_tap_0_2 = 5;
p_regs->sw34.pred_bc_tap_0_3 = 0x3FF;
p_regs->sw34.pred_bc_tap_1_0 = 1;
p_regs->sw34.pred_bc_tap_1_1 = 7;
p_regs->sw35.pred_bc_tap_1_2 = 7;
p_regs->sw35.pred_bc_tap_1_3 = 1;
p_regs->sw02.tiled_mode_lsb = 0;
return MPP_OK;
}
static MPP_RET set_regs_parameters(AvsdHalCtx_t *p_hal, HalDecTask *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdSyntax_t *p_syn = &p_hal->syn;
AvsdVdpu1Regs_t *p_regs = (AvsdVdpu1Regs_t *)p_hal->p_regs;
set_defalut_parameters(p_hal);
p_regs->sw02.dec_timeout_e = 1;
p_regs->sw02.dec_clk_gate_e = 1;
p_regs->sw01.dec_irq_dis = 0;
p_regs->sw03.rlc_mode_e = 0;
//!< set wrok_out pic info
if (p_hal->work_out < 0) {
p_hal->work_out = get_queue_pic(p_hal);
if (p_hal->work_out < 0) {
ret = MPP_NOK;
mpp_err_f("cannot get a pic_info buffer.\n");
goto __FAILED;
}
}
{
AvsdHalPic_t *p_work_out = &p_hal->pic[p_hal->work_out];
p_work_out->slot_idx = task->output;
p_work_out->pic_code_type = p_syn->pp.picCodingType;
p_work_out->picture_distance = p_syn->pp.pictureDistance;
}
//!< set register
p_regs->sw04.pic_mb_width = (p_syn->pp.horizontalSize + 15) >> 4;
p_regs->sw03.dec_mode = 11; //!< DEC_MODE_AVS
if (p_syn->pp.pictureStructure == FRAMEPICTURE) {
p_regs->sw03.pic_interlace_e = 0;
p_regs->sw03.pic_fieldmode_e = 0;
p_regs->sw03.pic_topfiled_e = 0;
} else {
p_regs->sw03.pic_interlace_e = 1;
p_regs->sw03.pic_fieldmode_e = 1;
p_regs->sw03.pic_topfiled_e = p_hal->first_field;
}
p_regs->sw04.pic_mb_height_p = (p_syn->pp.verticalSize + 15) >> 4;
//p_regs->sw07.avs_h_ext = (p_syn->pp.verticalSize + 15) >> 12;
if (p_syn->pp.picCodingType == BFRAME) {
p_regs->sw03.pic_b_e = 1;
} else {
p_regs->sw03.pic_b_e = 0;
}
p_regs->sw03.pic_inter_e = (p_syn->pp.picCodingType != IFRAME) ? 1 : 0;
mpp_log("data_offset %x\n", p_hal->data_offset);
p_regs->sw05.strm_start_bit = 8 * (p_hal->data_offset & 0x7);
p_hal->data_offset = (p_hal->data_offset & ~0x7);
p_regs->sw12.rlc_vlc_base = get_packet_fd(p_hal, task->input);
mpp_dev_set_reg_offset(p_hal->dev, 12, p_hal->data_offset);
p_regs->sw06.stream_len = p_syn->bitstream_size - p_hal->data_offset;
p_regs->sw03.pic_fixed_quant = p_syn->pp.fixedPictureQp;
p_regs->sw06.init_qp = p_syn->pp.pictureQp;
p_regs->sw13.dec_out_base = get_frame_fd(p_hal, task->output);
if (p_syn->pp.pictureStructure == FIELDPICTURE && !p_hal->first_field) {
//!< start of bottom field line
mpp_dev_set_reg_offset(p_hal->dev, 13, p_syn->pp.horizontalSize);
}
{
RK_S32 tmp_fwd = -1;
RK_S32 refer0 = -1;
RK_S32 refer1 = -1;
tmp_fwd = (p_hal->work1 < 0) ? p_hal->work0 : p_hal->work1;
tmp_fwd = (tmp_fwd < 0) ? p_hal->work_out : tmp_fwd;
refer0 = (task->refer[0] < 0) ? task->output : task->refer[0];
refer1 = (task->refer[1] < 0) ? refer0 : task->refer[1];
if (!p_hal->first_field
&& p_syn->pp.pictureStructure == FIELDPICTURE
&& p_syn->pp.picCodingType != BFRAME) {
p_regs->sw14.refer0_base = get_frame_fd(p_hal, task->output);
p_regs->sw15.refer1_base = get_frame_fd(p_hal, refer0);
p_regs->sw16.refer2_base = get_frame_fd(p_hal, refer0);
p_regs->sw17.refer3_base = get_frame_fd(p_hal, refer1);
} else {
p_regs->sw14.refer0_base = get_frame_fd(p_hal, refer0);
p_regs->sw15.refer1_base = get_frame_fd(p_hal, refer0);
p_regs->sw16.refer2_base = get_frame_fd(p_hal, refer1);
p_regs->sw17.refer3_base = get_frame_fd(p_hal, refer1);
}
}
//!< block distances
if (p_syn->pp.pictureStructure == FRAMEPICTURE) {
if (p_syn->pp.picCodingType == BFRAME) {
RK_S32 tmp = 0;
//!< current to future anchor
if (p_hal->work0 >= 0) {
tmp = (2 * p_hal->pic[p_hal->work0].picture_distance -
2 * p_syn->pp.pictureDistance + 512) & 0x1FF;
}
//!< prevent division by zero
if (!tmp) tmp = 2;
p_regs->sw31.ref_dist_cur_2 = tmp;
p_regs->sw31.ref_dist_cur_3 = tmp;
p_regs->sw29.ref_invd_cur_2 = 512 / tmp;
p_regs->sw29.ref_invd_cur_3 = 512 / tmp;
//!< current to past anchor
if (p_hal->work1 >= 0) {
tmp = (2 * p_syn->pp.pictureDistance -
2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF;
if (!tmp) tmp = 2;
}
p_regs->sw30.ref_dist_cur_0 = tmp;
p_regs->sw30.ref_dist_cur_1 = tmp;
p_regs->sw28.ref_invd_cur_0 = 512 / tmp;
p_regs->sw28.ref_invd_cur_1 = 512 / tmp;
//!< future anchor to past anchor
if (p_hal->work0 >= 0 && p_hal->work1 >= 0) {
tmp = (2 * p_hal->pic[p_hal->work0].picture_distance -
2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF;
if (!tmp) tmp = 2;
}
tmp = 16384 / tmp;
p_regs->sw32.ref_invd_col_0 = tmp;
p_regs->sw32.ref_invd_col_1 = tmp;
//!< future anchor to previous past anchor
tmp = p_hal->future2prev_past_dist;
tmp = 16384 / tmp;
p_regs->sw33.ref_invd_col_2 = tmp;
p_regs->sw33.ref_invd_col_3 = tmp;
} else {
RK_S32 tmp = 0;
//!< current to past anchor
if (p_hal->work0 >= 0) {
tmp = (2 * p_syn->pp.pictureDistance -
2 * p_hal->pic[p_hal->work0].picture_distance - 512) & 0x1FF;
}
if (!tmp) tmp = 2;
p_regs->sw30.ref_dist_cur_0 = tmp;
p_regs->sw30.ref_dist_cur_1 = tmp;
p_regs->sw28.ref_invd_cur_0 = 512 / tmp;
p_regs->sw28.ref_invd_cur_1 = 512 / tmp;
//!< current to previous past anchor
if (p_hal->work1 >= 0) {
tmp = (2 * p_syn->pp.pictureDistance -
2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF;
if (!tmp) tmp = 2;
}
//!< this will become "future to previous past" for next B
p_hal->future2prev_past_dist = tmp;
p_regs->sw31.ref_dist_cur_2 = tmp;
p_regs->sw31.ref_dist_cur_3 = tmp;
p_regs->sw29.ref_invd_cur_2 = 512 / tmp;
p_regs->sw29.ref_invd_cur_3 = 512 / tmp;
p_regs->sw32.ref_invd_col_0 = 0;
p_regs->sw32.ref_invd_col_1 = 0;
p_regs->sw33.ref_invd_col_2 = 0;
p_regs->sw33.ref_invd_col_3 = 0;
}
} else {
//!< field interlaced
if (p_syn->pp.picCodingType == BFRAME) {
RK_S32 tmp = 0;
//!< block distances
if (p_hal->work0 >= 0) {
tmp = (2 * p_hal->pic[p_hal->work0].picture_distance -
2 * p_syn->pp.pictureDistance + 512) & 0x1FF;
}
//!< prevent division by zero
if (!tmp) tmp = 2;
if (p_hal->first_field) {
p_regs->sw31.ref_dist_cur_2 = tmp;
p_regs->sw31.ref_dist_cur_3 = tmp + 1;
p_regs->sw29.ref_invd_cur_2 = 512 / tmp;
p_regs->sw29.ref_invd_cur_3 = 512 / (tmp + 1);
} else {
p_regs->sw31.ref_dist_cur_2 = tmp - 1;
p_regs->sw31.ref_dist_cur_3 = tmp;
p_regs->sw29.ref_invd_cur_2 = 512 / (tmp - 1);
p_regs->sw29.ref_invd_cur_3 = 512 / tmp;
}
if (p_hal->work1 >= 0) {
tmp = (2 * p_syn->pp.pictureDistance -
2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF;
if (!tmp) tmp = 2;
}
if (p_hal->first_field) {
p_regs->sw30.ref_dist_cur_0 = (tmp - 1);
p_regs->sw30.ref_dist_cur_1 = tmp;
p_regs->sw28.ref_invd_cur_0 = 512 / (tmp - 1);
p_regs->sw28.ref_invd_cur_1 = 512 / tmp;
} else {
p_regs->sw30.ref_dist_cur_0 = tmp;
p_regs->sw30.ref_dist_cur_1 = tmp + 1;
p_regs->sw28.ref_invd_cur_0 = 512 / tmp;
p_regs->sw28.ref_invd_cur_1 = 512 / (tmp + 1);
}
if (p_hal->work0 >= 0 && p_hal->work1 >= 0) {
tmp = (2 * p_hal->pic[p_hal->work0].picture_distance -
2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF;
if (!tmp) tmp = 2;
}
if (p_syn->pp.pbFieldEnhancedFlag && !p_hal->first_field) {
//!< in this case, BlockDistanceRef is different with before, the mvRef points to top field
p_regs->sw32.ref_invd_col_0 = 16384 / (tmp - 1);
p_regs->sw32.ref_invd_col_1 = 16384 / tmp;
//!< future anchor to previous past anchor
tmp = p_hal->future2prev_past_dist;
p_regs->sw33.ref_invd_col_2 = 16384 / (tmp - 1);
p_regs->sw33.ref_invd_col_3 = 16384 / tmp;
} else {
if (p_hal->first_field) {
p_regs->sw32.ref_invd_col_0 = 16384 / (tmp - 1);
p_regs->sw32.ref_invd_col_1 = 16384 / tmp;
} else {
p_regs->sw32.ref_invd_col_0 = 16384;
p_regs->sw32.ref_invd_col_1 = 16384 / tmp;
p_regs->sw33.ref_invd_col_2 = 16384 / (tmp + 1);
}
//!< future anchor to previous past anchor
tmp = p_hal->future2prev_past_dist;
if (p_hal->first_field) {
p_regs->sw33.ref_invd_col_2 = 16384 / (tmp - 1);
p_regs->sw33.ref_invd_col_3 = 16384 / tmp;
} else {
p_regs->sw33.ref_invd_col_3 = 16384 / tmp;
}
}
} else {
RK_S32 tmp = 0;
if (p_hal->work0 >= 0) {
tmp = (2 * p_syn->pp.pictureDistance -
2 * p_hal->pic[p_hal->work0].picture_distance - 512) & 0x1FF;
}
if (!tmp) tmp = 2;
if (!p_hal->first_field) {
p_regs->sw30.ref_dist_cur_0 = 1;
p_regs->sw31.ref_dist_cur_2 = tmp + 1;
p_regs->sw28.ref_invd_cur_0 = 512;
p_regs->sw29.ref_invd_cur_2 = 512 / (tmp + 1);
} else {
p_regs->sw30.ref_dist_cur_0 = tmp - 1;
p_regs->sw28.ref_invd_cur_0 = 512 / (tmp - 1);
}
p_regs->sw30.ref_dist_cur_1 = tmp;
p_regs->sw28.ref_invd_cur_1 = 512 / tmp;
if (p_hal->work1 >= 0) {
tmp = (2 * p_syn->pp.pictureDistance -
2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF;
if (!tmp) tmp = 2;
}
//!< this will become "future to previous past" for next B
p_hal->future2prev_past_dist = tmp;
if (p_hal->first_field) {
p_regs->sw31.ref_dist_cur_2 = tmp - 1;
p_regs->sw31.ref_dist_cur_3 = tmp;
p_regs->sw29.ref_invd_cur_2 = 512 / (tmp - 1);
p_regs->sw29.ref_invd_cur_3 = 512 / tmp;
} else {
p_regs->sw31.ref_dist_cur_3 = tmp;
p_regs->sw29.ref_invd_cur_3 = 512 / tmp;
}
p_regs->sw32.ref_invd_col_0 = 0;
p_regs->sw32.ref_invd_col_1 = 0;
p_regs->sw33.ref_invd_col_2 = 0;
p_regs->sw33.ref_invd_col_3 = 0;
}
}
p_regs->sw48.startmb_x = 0;
p_regs->sw48.startmb_y = 0;
p_regs->sw03.filtering_dis = p_syn->pp.loopFilterDisable;
p_regs->sw05.alpha_offset = p_syn->pp.alphaOffset;
p_regs->sw05.beta_offset = p_syn->pp.betaOffset;
p_regs->sw03.skip_mode = p_syn->pp.skipModeFlag;
p_regs->sw04.pic_refer_flag = p_syn->pp.pictureReferenceFlag;
if (p_syn->pp.picCodingType == PFRAME
|| (p_syn->pp.picCodingType == IFRAME && !p_hal->first_field)) {
p_regs->sw03.write_mvs_e = 1;
} else {
p_regs->sw03.write_mvs_e = 0;
}
//!< set mv base
p_regs->sw41.dir_mv_base = mpp_buffer_get_fd(p_hal->mv_buf);
if (p_hal->first_field ||
(p_syn->pp.picCodingType == BFRAME && p_hal->prev_pic_structure)) {
} else {
RK_U32 frame_width = 0, frame_height = 0, offset = 0;
frame_width = (p_syn->pp.horizontalSize + 15) >> 4;
if (p_syn->pp.progressiveFrame)
frame_height = (p_syn->pp.verticalSize + 15) >> 4;
else
frame_height = 2 * ((p_syn->pp.verticalSize + 31) >> 5);
offset = MPP_ALIGN(frame_width * frame_height / 2, 2) * 16;
mpp_dev_set_reg_offset(p_hal->dev, 41, offset);
}
{
RK_U32 pic_type = 0;
RK_U32 prev_anc_type = 0;
if (p_hal->work0 >= 0) {
pic_type = p_hal->pic[p_hal->work0].pic_type;
}
prev_anc_type = !pic_type || (!p_hal->first_field && !p_hal->prev_pic_structure);
p_regs->sw18.prev_anc_type = prev_anc_type;
}
//!< b-picture needs to know if future reference is field or frame coded
// p_regs->sw16.refer2_field_e = (!p_hal->prev_pic_structure) ? 1 : 0;
// p_regs->sw17.refer3_field_e = (!p_hal->prev_pic_structure) ? 1 : 0;
if (!p_hal->prev_pic_structure) {
mpp_dev_set_reg_offset(p_hal->dev, 16, 2);
mpp_dev_set_reg_offset(p_hal->dev, 17, 3);
}
p_regs->sw03.dec_out_dis = 0;
p_regs->sw01.dec_e = 1;
return MPP_OK;
__FAILED:
return ret;
}
static MPP_RET update_parameters(AvsdHalCtx_t *p_hal)
{
AvsdSyntax_t *p_syn = &p_hal->syn;
if (p_syn->pp.pictureStructure == FRAMEPICTURE || !p_hal->first_field) {
p_hal->first_field = 1;
if (p_syn->pp.picCodingType != BFRAME) {
RK_S32 temp = p_hal->work1;
p_hal->work1 = p_hal->work0;
p_hal->work0 = p_hal->work_out;
p_hal->pic[p_hal->work_out].pic_type = p_syn->pp.picCodingType == IFRAME;
p_hal->work_out = temp;
p_hal->prev_pic_structure = p_syn->pp.pictureStructure;
}
p_hal->prev_pic_code_type = p_syn->pp.picCodingType;
} else {
p_hal->first_field = 0;
}
return MPP_OK;
}
static MPP_RET repeat_other_field(AvsdHalCtx_t *p_hal, HalTaskInfo *task)
{
RK_U8 i = 0;
RK_U8 *pdata = NULL;
MppBuffer mbuffer = NULL;
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdVdpu1Regs_t *p_regs = (AvsdVdpu1Regs_t *)p_hal->p_regs;
//!< re-find start code and calculate offset
p_hal->data_offset = p_regs->sw12.rlc_vlc_base >> 10;
p_hal->data_offset += p_hal->syn.bitstream_offset;
p_hal->data_offset -= MPP_MIN(p_hal->data_offset, 8);
mpp_buf_slot_get_prop(p_hal->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer);
pdata = (RK_U8 *)mpp_buffer_get_ptr(mbuffer) + p_hal->data_offset;
while (i < 16) {
if (pdata[i] == 0 && pdata[i + 1] == 0 && pdata[i + 2] == 1) {
p_hal->data_offset += i;
break;
}
i++;
}
AVSD_HAL_DBG(AVSD_HAL_DBG_OFFSET, "frame_no=%d, i=%d, offset=%d\n",
p_hal->frame_no, i, p_hal->data_offset);
//!< re-generate register
FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec));
hal_avsd_vdpu1_start((void *)p_hal, task);
hal_avsd_vdpu1_wait((void *)p_hal, task);
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief
* init
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu1_init(void *decoder, MppHalCfg *cfg)
{
MPP_RET ret = MPP_ERR_UNKNOW;
RK_U32 buf_size = 0;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("AVS_vdpu1 In.");
buf_size = (1920 * 1088) * 2;
FUN_CHECK(ret = mpp_buffer_get(p_hal->buf_group, &p_hal->mv_buf, buf_size));
p_hal->p_regs = mpp_calloc_size(RK_U32, sizeof(AvsdVdpu1Regs_t));
MEM_CHECK(ret, p_hal->p_regs);
mpp_slots_set_prop(p_hal->frame_slots, SLOTS_HOR_ALIGN, avsd_hor_align);
mpp_slots_set_prop(p_hal->frame_slots, SLOTS_VER_ALIGN, avsd_ver_align);
mpp_slots_set_prop(p_hal->frame_slots, SLOTS_LEN_ALIGN, avsd_len_align);
p_hal->regs_num = 60;
//!< initial for control
p_hal->first_field = 1;
p_hal->prev_pic_structure = 0; //!< field
memset(p_hal->pic, 0, sizeof(p_hal->pic));
p_hal->work_out = -1;
p_hal->work0 = -1;
p_hal->work1 = -1;
AVSD_HAL_TRACE("Out.");
(void)cfg;
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief
* deinit
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu1_deinit(void *decoder)
{
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
if (p_hal->mv_buf) {
mpp_buffer_put(p_hal->mv_buf);
p_hal->mv_buf = NULL;
}
MPP_FREE(p_hal->p_regs);
AVSD_HAL_TRACE("Out.");
return MPP_OK;
}
/*!
***********************************************************************
* \brief
* generate register
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu1_gen_regs(void *decoder, HalTaskInfo *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
if (task->dec.flags.parse_err || task->dec.flags.ref_err) {
goto __RETURN;
}
p_hal->data_offset = p_hal->syn.bitstream_offset;
FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec));
__RETURN:
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief h
* start hard
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu1_start(void *decoder, HalTaskInfo *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
if (task->dec.flags.parse_err || task->dec.flags.ref_err) {
goto __RETURN;
}
do {
MppDevRegWrCfg wr_cfg;
MppDevRegRdCfg rd_cfg;
RK_U32 reg_size = 101 * sizeof(RK_U32);
wr_cfg.reg = p_hal->p_regs;
wr_cfg.size = reg_size;
wr_cfg.offset = 0;
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_REG_WR, &wr_cfg);
if (ret) {
mpp_err_f("set register write failed %d\n", ret);
break;
}
rd_cfg.reg = p_hal->p_regs;
rd_cfg.size = reg_size;
rd_cfg.offset = 0;
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_REG_RD, &rd_cfg);
if (ret) {
mpp_err_f("set register read failed %d\n", ret);
break;
}
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_CMD_SEND, NULL);
if (ret) {
mpp_err_f("send cmd failed %d\n", ret);
break;
}
} while (0);
__RETURN:
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}
/*!
***********************************************************************
* \brief
* wait hard
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu1_wait(void *decoder, HalTaskInfo *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
if (task->dec.flags.parse_err || task->dec.flags.ref_err) {
goto __SKIP_HARD;
}
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_CMD_POLL, NULL);
if (ret)
mpp_err_f("poll cmd failed %d\n", ret);
__SKIP_HARD:
if (p_hal->dec_cb) {
DecCbHalDone param;
param.task = (void *)&task->dec;
param.regs = (RK_U32 *)p_hal->p_regs;
if (!((AvsdVdpu1Regs_t *)p_hal->p_regs)->sw01.dec_rdy_int) {
param.hard_err = 1;
} else
param.hard_err = 0;
mpp_callback(p_hal->dec_cb, &param);
AVSD_HAL_DBG(AVSD_HAL_DBG_WAIT, "reg[1]=%08x, ref=%d, dpberr=%d, harderr=%d\n",
p_hal->p_regs[1], task->dec.flags.used_for_ref, task->dec.flags.ref_err, param.hard_err);
}
update_parameters(p_hal);
memset(&p_hal->p_regs[1], 0, sizeof(RK_U32));
if (!p_hal->first_field && p_hal->syn.pp.pictureStructure == FIELDPICTURE &&
!task->dec.flags.parse_err && !task->dec.flags.ref_err) {
repeat_other_field(p_hal, task);
}
p_hal->frame_no++;
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}
/*!
***********************************************************************
* \brief
* reset
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu1_reset(void *decoder)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
p_hal->first_field = 1;
p_hal->prev_pic_structure = 0; //!< field
memset(p_hal->pic, 0, sizeof(p_hal->pic));
p_hal->work_out = -1;
p_hal->work0 = -1;
p_hal->work1 = -1;
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}
/*!
***********************************************************************
* \brief
* flush
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu1_flush(void *decoder)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AVSD_HAL_TRACE("In.");
(void)decoder;
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}
/*!
***********************************************************************
* \brief
* control
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu1_control(void *decoder, MpiCmd cmd_type, void *param)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AVSD_HAL_TRACE("In.");
(void)decoder;
(void)cmd_type;
(void)param;
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}

View File

@@ -0,0 +1,39 @@
/*
* 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_AVSD_VDPU1_H__
#define __HAL_AVSD_VDPU1_H__
#include "mpp_hal.h"
#ifdef __cplusplus
extern "C" {
#endif
MPP_RET hal_avsd_vdpu1_init(void *decoder, MppHalCfg *cfg);
MPP_RET hal_avsd_vdpu1_deinit(void *decoder);
MPP_RET hal_avsd_vdpu1_gen_regs(void *decoder, HalTaskInfo *task);
MPP_RET hal_avsd_vdpu1_start(void *decoder, HalTaskInfo *task);
MPP_RET hal_avsd_vdpu1_wait(void *decoder, HalTaskInfo *task);
MPP_RET hal_avsd_vdpu1_reset(void *decoder);
MPP_RET hal_avsd_vdpu1_flush(void *decoder);
MPP_RET hal_avsd_vdpu1_control(void *decoder, MpiCmd cmd_type, void *param);
#ifdef __cplusplus
}
#endif
#endif /*__HAL_AVSD_VDPU1_H__*/

View File

@@ -0,0 +1,247 @@
/*
* 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_AVSD_VDPU1_REG_H__
#define __HAL_AVSD_VDPU1_REG_H__
typedef struct {
RK_U32 sw00;
struct {
RK_U32 dec_e : 1;
RK_U32 reserve0 : 3;
RK_U32 dec_irq_dis : 1;
RK_U32 dec_abort_e : 1;
RK_U32 reserve1 : 2;
RK_U32 dec_irq : 1;
RK_U32 reserve2 : 2;
RK_U32 dec_abort_int : 1;
RK_U32 dec_rdy_int : 1;
RK_U32 dec_bus_int : 1;
RK_U32 dec_buffer_int : 1;
RK_U32 reserve3 : 1;
RK_U32 dec_error_int : 1;
RK_U32 reserve4 : 1;
RK_U32 dec_timeout : 1;
RK_U32 reserve5 : 5;
RK_U32 dec_pic_inf : 1;
RK_U32 reserve6 : 7;
} sw01;
union {
struct {
RK_U32 dec_max_burst : 5;
RK_U32 dec_scmd_dis : 1;
RK_U32 dec_adv_pre_dis : 1;
RK_U32 tiled_mode_lsb : 1;
RK_U32 dec_out_endian : 1;
RK_U32 dec_in_endian : 1;
RK_U32 dec_clk_gate_e : 1;
RK_U32 dec_latency : 6;
RK_U32 dec_out_tiled_e : 1;
RK_U32 dec_data_disc_e : 1;
RK_U32 dec_outswap32_e : 1;
RK_U32 dec_inswap32_e : 1;
RK_U32 dec_strendian_e : 1;
RK_U32 dec_strswap32_e : 1;
RK_U32 dec_timeout_e : 1;
RK_U32 dec_axi_rd_id : 8;
};
struct {
RK_U32 reserve0 : 5;
RK_U32 priority_mode : 3;
RK_U32 reserve1 : 9;
RK_U32 tiled_mode_msb : 1;
RK_U32 dec_2chan_dis : 1;
RK_U32 reserve2 : 13;
};
} sw02;
struct {
RK_U32 dec_axi_wr_id : 8;
RK_U32 dec_ahb_hlock_e : 1;
RK_U32 picord_count_e : 1;
RK_U32 reserve0 : 1;
RK_U32 reftopfirst_e : 1;
RK_U32 write_mvs_e : 1;
RK_U32 pic_fixed_quant : 1;
RK_U32 filtering_dis : 1;
RK_U32 dec_out_dis : 1;
RK_U32 ref_topfield_e : 1;
RK_U32 reserve1 : 1;
RK_U32 fwd_interlace_e : 1;
RK_U32 pic_topfiled_e : 1;
RK_U32 pic_inter_e : 1;
RK_U32 pic_b_e : 1;
RK_U32 pic_fieldmode_e : 1;
RK_U32 pic_interlace_e : 1;
RK_U32 reserve2 : 2;
RK_U32 skip_mode : 1;
RK_U32 rlc_mode_e : 1;
RK_U32 dec_mode : 4;
} sw03;
struct {
RK_U32 pic_refer_flag : 1;
RK_U32 reverse0 : 10;
RK_U32 pic_mb_height_p : 8;
RK_U32 mb_width_off : 4;
RK_U32 pic_mb_width : 9;
} sw04;
union {
struct {
RK_U32 fieldpic_flag_e : 1;
RK_S32 reserve0 : 31;
};
struct {
RK_U32 beta_offset : 5;
RK_U32 alpha_offset : 5;
RK_U32 reserve1 : 16;
RK_U32 strm_start_bit : 6;
};
} sw05;
struct {
RK_U32 stream_len : 24;
RK_U32 stream_len_ext : 1;
RK_U32 init_qp : 6;
RK_U32 start_code_e : 1;
} sw06;
RK_U32 sw07_11[5];
struct {
RK_U32 rlc_vlc_base : 32;
} sw12;
struct {
RK_U32 dec_out_base : 32;
} sw13;
union {
RK_U32 refer0_base : 32;
struct { //!< left move 10bit
RK_U32 reserve0 : 10;
RK_U32 refer0_topc_e : 1;
RK_U32 refer0_field_e : 1;
RK_U32 reserve1 : 20;
};
} sw14;
union {
struct {
RK_U32 refer1_base : 32;
};
struct { //!< left move 10bit
RK_U32 reserve0 : 10;
RK_U32 refer1_topc_e : 1;
RK_U32 refer1_field_e : 1;
RK_U32 reserve1 : 20;
};
} sw15;
union {
struct {
RK_U32 refer2_base : 32;
};
struct { //!< left move 10bit
RK_U32 reserve0 : 10;
RK_U32 refer2_topc_e : 1;
RK_U32 refer2_field_e : 1;
RK_U32 reserve1 : 20;
};
} sw16;
union {
struct {
RK_U32 refer3_base : 32;
};
struct { //!< left move 10bit
RK_U32 reserve0 : 10;
RK_U32 refer3_topc_e : 1;
RK_U32 refer3_field_e : 1;
RK_U32 reserve1 : 20;
};
} sw17;
struct {
RK_U32 prev_anc_type : 1;
RK_U32 reverse0 : 31;
} sw18;
RK_U32 sw19_27[9];
struct {
RK_U32 ref_invd_cur_0 : 16;
RK_U32 ref_invd_cur_1 : 16;
} sw28;
struct {
RK_U32 ref_invd_cur_2 : 16;
RK_U32 ref_invd_cur_3 : 16;
} sw29;
struct {
RK_U32 ref_dist_cur_0 : 16;
RK_U32 ref_dist_cur_1 : 16;
} sw30;
struct {
RK_U32 ref_dist_cur_2 : 16;
RK_U32 ref_dist_cur_3 : 16;
} sw31;
struct {
RK_U32 ref_invd_col_0 : 16;
RK_U32 ref_invd_col_1 : 16;
} sw32;
struct {
RK_U32 ref_invd_col_2 : 16;
RK_U32 ref_invd_col_3 : 16;
} sw33;
struct {
RK_U32 reserve0 : 2;
RK_U32 pred_bc_tap_1_1 : 10;
RK_U32 pred_bc_tap_1_0 : 10;
RK_U32 pred_bc_tap_0_3 : 10;
} sw34;
struct {
RK_U32 reserve0 : 12;
RK_U32 pred_bc_tap_1_3 : 10;
RK_U32 pred_bc_tap_1_2 : 10;
} sw35;
RK_U32 sw36_40[5];
struct {
RK_U32 dir_mv_base : 32;
} sw41;
RK_U32 sw42_47[6];
struct {
RK_U32 reserve0 : 14;
RK_U32 startmb_y : 9;
RK_U32 startmb_x : 9;
} sw48;
struct {
RK_U32 reserve0 : 2;
RK_U32 pred_bc_tap_0_2 : 10;
RK_U32 pred_bc_tap_0_1 : 10;
RK_U32 pred_bc_tap_0_0 : 10;
} sw49;
RK_U32 sw50_54[5];
struct {
RK_U32 apf_threshold : 14;
RK_U32 refbu2_picid : 5;
RK_U32 refbu2_thr : 12;
RK_U32 refbu2_buf_e : 1;
} sw55;
RK_U32 sw56;
struct {
RK_U32 stream_len_ext : 1;
RK_U32 inter_dblspeed : 1;
RK_U32 intra_dblspeed : 1;
RK_U32 intra_dbl3t : 1;
RK_U32 bus_pos_sel : 1;
RK_U32 axi_sel : 1;
RK_U32 pref_sigchan : 1;
RK_U32 cache_en : 1;
RK_U32 reserve : 24;
} sw57;
RK_U32 sw58_59[2];
RK_U32 resever[40];
} AvsdVdpu1Regs_t;
#endif /*__HAL_AVSD_VDPU1_REG_H__*/

View File

@@ -0,0 +1,727 @@
/*
* 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_avsd_vdpu2"
#include <string.h>
#include "mpp_debug.h"
#include "mpp_common.h"
#include "mpp_mem.h"
#include "mpp_device.h"
#include "mpp_dec_cb_param.h"
#include "hal_avsd_base.h"
#include "hal_avsd_vdpu2.h"
#include "hal_avsd_vdpu2_reg.h"
static MPP_RET set_defalut_parameters(AvsdHalCtx_t *p_hal)
{
AvsdVdpu2Regs_t *p_regs = (AvsdVdpu2Regs_t *)p_hal->p_regs;
p_regs->sw54.dec_out_endian = 1;
p_regs->sw54.dec_in_endian = 0;
p_regs->sw54.dec_strendian_e = 1;
p_regs->sw56.dec_max_burlen = 16;
p_regs->sw50.dec_ascmd0_dis = 0;
p_regs->sw50.adv_pref_dis = 0;
p_regs->sw52.adv_pref_thrd = 8;
p_regs->sw50.adtion_latency = 0;
p_regs->sw56.dec_data_discd_en = 0;
p_regs->sw54.dec_out_wordsp = 1;
p_regs->sw54.dec_in_wordsp = 1;
p_regs->sw54.dec_strm_wordsp = 1;
p_regs->sw55.timeout_det_sts = 0;
p_regs->sw57.dec_clkgate_en = 1;
p_regs->sw55.dec_irq_dis = 0;
p_regs->sw56.dec_axi_id_rd = 0xFF;
p_regs->sw56.dec_axi_id_wr = 0;
p_regs->sw59.pred_bc_tap_0_0 = 0x3FF;
p_regs->sw59.pred_bc_tap_0_1 = 5;
p_regs->sw59.pred_bc_tap_0_2 = 5;
p_regs->sw153.pred_bc_tap_0_3 = 0x3FF;
p_regs->sw153.pred_bc_tap_1_0 = 1;
p_regs->sw153.pred_bc_tap_1_1 = 7;
p_regs->sw154.pred_bc_tap_1_2 = 7;
p_regs->sw154.pred_bc_tap_1_3 = 1;
p_regs->sw50.dec_tiled_lsb = 0;
return MPP_OK;
}
static MPP_RET set_regs_parameters(AvsdHalCtx_t *p_hal, HalDecTask *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdSyntax_t *p_syn = &p_hal->syn;
AvsdVdpu2Regs_t *p_regs = (AvsdVdpu2Regs_t *)p_hal->p_regs;
set_defalut_parameters(p_hal);
p_regs->sw57.timeout_sts_en = 1;
p_regs->sw57.dec_clkgate_en = 1;
p_regs->sw55.dec_irq_dis = 0;
//!< set wrok_out pic info
if (p_hal->work_out < 0) {
p_hal->work_out = get_queue_pic(p_hal);
if (p_hal->work_out < 0) {
ret = MPP_NOK;
mpp_err_f("cannot get a pic_info buffer.\n");
goto __FAILED;
}
}
{
AvsdHalPic_t *p_work_out = &p_hal->pic[p_hal->work_out];
p_work_out->slot_idx = task->output;
p_work_out->pic_code_type = p_syn->pp.picCodingType;
p_work_out->picture_distance = p_syn->pp.pictureDistance;
}
//!< set register
p_regs->sw120.pic_mb_width = (p_syn->pp.horizontalSize + 15) >> 4;
p_regs->sw53.dec_fmt_sel = 11; //!< DEC_MODE_AVS
if (p_syn->pp.pictureStructure == FRAMEPICTURE) {
p_regs->sw57.pic_interlace_e = 0; //!< interlace_e
p_regs->sw57.pic_fieldmode_e = 0; //!< fieldmode_e
p_regs->sw57.pic_topfield_e = 0; //!< topfield_e
} else {
p_regs->sw57.pic_interlace_e = 1;
p_regs->sw57.pic_fieldmode_e = 1;
p_regs->sw57.pic_topfield_e = p_hal->first_field;
}
p_regs->sw120.pic_mb_height_p = (p_syn->pp.verticalSize + 15) >> 4;
p_regs->sw121.avs_h_ext = (p_syn->pp.verticalSize + 15) >> 12;
p_regs->sw57.pic_b_e = (p_syn->pp.picCodingType == BFRAME);
p_regs->sw57.pic_inter_e = (p_syn->pp.picCodingType != IFRAME) ? 1 : 0;
p_regs->sw122.strm_start_bit = 8 * (p_hal->data_offset & 0x7);
p_hal->data_offset = (p_hal->data_offset & ~0x7);
p_regs->sw64.rlc_vlc_st_adr = get_packet_fd(p_hal, task->input);
mpp_dev_set_reg_offset(p_hal->dev, 64, p_hal->data_offset);
p_regs->sw51.stream_len = p_syn->bitstream_size - p_hal->data_offset;
p_regs->sw50.dec_fixed_quant = p_syn->pp.fixedPictureQp;
p_regs->sw51.init_qp = p_syn->pp.pictureQp;
p_regs->sw63.dec_out_st_adr = get_frame_fd(p_hal, task->output);
if (p_syn->pp.pictureStructure == FIELDPICTURE && !p_hal->first_field) {
//!< start of bottom field line
mpp_dev_set_reg_offset(p_hal->dev, 63, p_syn->pp.horizontalSize);
}
{
RK_S32 tmp_fwd = -1;
RK_S32 refer0 = -1;
RK_S32 refer1 = -1;
tmp_fwd = (p_hal->work1 < 0) ? p_hal->work0 : p_hal->work1;
tmp_fwd = (tmp_fwd < 0) ? p_hal->work_out : tmp_fwd;
refer0 = (task->refer[0] < 0) ? task->output : task->refer[0];
refer1 = (task->refer[1] < 0) ? refer0 : task->refer[1];
if (!p_hal->first_field
&& p_syn->pp.pictureStructure == FIELDPICTURE
&& p_syn->pp.picCodingType != BFRAME) {
p_regs->sw131.refer0_base = get_frame_fd(p_hal, task->output);
p_regs->sw148.refer1_base = get_frame_fd(p_hal, refer0);
p_regs->sw134.refer2_base = get_frame_fd(p_hal, refer0);
p_regs->sw135.refer3_base = get_frame_fd(p_hal, refer1);
} else {
p_regs->sw131.refer0_base = get_frame_fd(p_hal, refer0);
p_regs->sw148.refer1_base = get_frame_fd(p_hal, refer0);
p_regs->sw134.refer2_base = get_frame_fd(p_hal, refer1);
p_regs->sw135.refer3_base = get_frame_fd(p_hal, refer1);
}
}
//!< block distances
if (p_syn->pp.pictureStructure == FRAMEPICTURE) {
if (p_syn->pp.picCodingType == BFRAME) {
RK_S32 tmp = 0;
//!< current to future anchor
if (p_hal->work0 >= 0) {
tmp = (2 * p_hal->pic[p_hal->work0].picture_distance -
2 * p_syn->pp.pictureDistance + 512) & 0x1FF;
}
//!< prevent division by zero
if (!tmp) tmp = 2;
p_regs->sw133.ref_dist_cur_2 = tmp;
p_regs->sw133.ref_dist_cur_3 = tmp;
p_regs->sw147.ref_invd_cur_2 = 512 / tmp;
p_regs->sw147.ref_invd_cur_3 = 512 / tmp;
//!< current to past anchor
if (p_hal->work1 >= 0) {
tmp = (2 * p_syn->pp.pictureDistance -
2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF;
if (!tmp) tmp = 2;
}
p_regs->sw132.ref_dist_cur_0 = tmp;
p_regs->sw132.ref_dist_cur_1 = tmp;
p_regs->sw146.ref_invd_cur_0 = 512 / tmp;
p_regs->sw146.ref_invd_cur_1 = 512 / tmp;
//!< future anchor to past anchor
if (p_hal->work0 >= 0 && p_hal->work1 >= 0) {
tmp = (2 * p_hal->pic[p_hal->work0].picture_distance -
2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF;
if (!tmp) tmp = 2;
}
tmp = 16384 / tmp;
p_regs->sw129.ref_invd_col_0 = tmp;
p_regs->sw129.ref_invd_col_1 = tmp;
//!< future anchor to previous past anchor
tmp = p_hal->future2prev_past_dist;
tmp = 16384 / tmp;
p_regs->sw130.ref_invd_col_2 = tmp;
p_regs->sw130.ref_invd_col_3 = tmp;
} else {
RK_S32 tmp = 0;
//!< current to past anchor
if (p_hal->work0 >= 0) {
tmp = (2 * p_syn->pp.pictureDistance -
2 * p_hal->pic[p_hal->work0].picture_distance - 512) & 0x1FF;
}
if (!tmp) tmp = 2;
p_regs->sw132.ref_dist_cur_0 = tmp;
p_regs->sw132.ref_dist_cur_1 = tmp;
p_regs->sw146.ref_invd_cur_0 = 512 / tmp;
p_regs->sw146.ref_invd_cur_1 = 512 / tmp;
//!< current to previous past anchor
if (p_hal->work1 >= 0) {
tmp = (2 * p_syn->pp.pictureDistance -
2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF;
if (!tmp) tmp = 2;
}
//!< this will become "future to previous past" for next B
p_hal->future2prev_past_dist = tmp;
p_regs->sw133.ref_dist_cur_2 = tmp;
p_regs->sw133.ref_dist_cur_3 = tmp;
p_regs->sw147.ref_invd_cur_2 = 512 / tmp;
p_regs->sw147.ref_invd_cur_3 = 512 / tmp;
p_regs->sw129.ref_invd_col_0 = 0;
p_regs->sw129.ref_invd_col_1 = 0;
p_regs->sw130.ref_invd_col_2 = 0;
p_regs->sw130.ref_invd_col_3 = 0;
}
} else {
//!< field interlaced
if (p_syn->pp.picCodingType == BFRAME) {
RK_S32 tmp = 0;
//!< block distances
if (p_hal->work0 >= 0) {
tmp = (2 * p_hal->pic[p_hal->work0].picture_distance -
2 * p_syn->pp.pictureDistance + 512) & 0x1FF;
}
//!< prevent division by zero
if (!tmp) tmp = 2;
if (p_hal->first_field) {
p_regs->sw133.ref_dist_cur_2 = tmp;
p_regs->sw133.ref_dist_cur_3 = tmp + 1;
p_regs->sw147.ref_invd_cur_2 = 512 / tmp;
p_regs->sw147.ref_invd_cur_3 = 512 / (tmp + 1);
} else {
p_regs->sw133.ref_dist_cur_2 = tmp - 1;
p_regs->sw133.ref_dist_cur_3 = tmp;
p_regs->sw147.ref_invd_cur_2 = 512 / (tmp - 1);
p_regs->sw147.ref_invd_cur_3 = 512 / tmp;
}
if (p_hal->work1 >= 0) {
tmp = (2 * p_syn->pp.pictureDistance -
2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF;
if (!tmp) tmp = 2;
}
if (p_hal->first_field) {
p_regs->sw132.ref_dist_cur_0 = (tmp - 1);
p_regs->sw132.ref_dist_cur_1 = tmp;
p_regs->sw146.ref_invd_cur_0 = 512 / (tmp - 1);
p_regs->sw146.ref_invd_cur_1 = 512 / tmp;
} else {
p_regs->sw132.ref_dist_cur_0 = tmp;
p_regs->sw132.ref_dist_cur_1 = tmp + 1;
p_regs->sw146.ref_invd_cur_0 = 512 / tmp;
p_regs->sw146.ref_invd_cur_1 = 512 / (tmp + 1);
}
if (p_hal->work0 >= 0 && p_hal->work1 >= 0) {
tmp = (2 * p_hal->pic[p_hal->work0].picture_distance -
2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF;
if (!tmp) tmp = 2;
}
if (p_syn->pp.pbFieldEnhancedFlag && !p_hal->first_field) {
//!< in this case, BlockDistanceRef is different with before, the mvRef points to top field
p_regs->sw129.ref_invd_col_0 = 16384 / (tmp - 1);
p_regs->sw129.ref_invd_col_1 = 16384 / tmp;
//!< future anchor to previous past anchor
tmp = p_hal->future2prev_past_dist;
p_regs->sw130.ref_invd_col_2 = 16384 / (tmp - 1);
p_regs->sw130.ref_invd_col_3 = 16384 / tmp;
} else {
if (p_hal->first_field) {
p_regs->sw129.ref_invd_col_0 = 16384 / (tmp - 1);
p_regs->sw129.ref_invd_col_1 = 16384 / tmp;
} else {
p_regs->sw129.ref_invd_col_0 = 16384;
p_regs->sw129.ref_invd_col_1 = 16384 / tmp;
p_regs->sw130.ref_invd_col_2 = 16384 / (tmp + 1);
}
//!< future anchor to previous past anchor
tmp = p_hal->future2prev_past_dist;
if (p_hal->first_field) {
p_regs->sw130.ref_invd_col_2 = 16384 / (tmp - 1);
p_regs->sw130.ref_invd_col_3 = 16384 / tmp;
} else {
p_regs->sw130.ref_invd_col_3 = 16384 / tmp;
}
}
} else {
RK_S32 tmp = 0;
if (p_hal->work0 >= 0) {
tmp = (2 * p_syn->pp.pictureDistance -
2 * p_hal->pic[p_hal->work0].picture_distance - 512) & 0x1FF;
}
if (!tmp) tmp = 2;
if (!p_hal->first_field) {
p_regs->sw132.ref_dist_cur_0 = 1;
p_regs->sw133.ref_dist_cur_2 = tmp + 1;
p_regs->sw146.ref_invd_cur_0 = 512;
p_regs->sw147.ref_invd_cur_2 = 512 / (tmp + 1);
} else {
p_regs->sw132.ref_dist_cur_0 = tmp - 1;
p_regs->sw146.ref_invd_cur_0 = 512 / (tmp - 1);
}
p_regs->sw132.ref_dist_cur_1 = tmp;
p_regs->sw146.ref_invd_cur_1 = 512 / tmp;
if (p_hal->work1 >= 0) {
tmp = (2 * p_syn->pp.pictureDistance -
2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF;
if (!tmp) tmp = 2;
}
//!< this will become "future to previous past" for next B
p_hal->future2prev_past_dist = tmp;
if (p_hal->first_field) {
p_regs->sw133.ref_dist_cur_2 = tmp - 1;
p_regs->sw133.ref_dist_cur_3 = tmp;
p_regs->sw147.ref_invd_cur_2 = 512 / (tmp - 1);
p_regs->sw147.ref_invd_cur_3 = 512 / tmp;
} else {
p_regs->sw133.ref_dist_cur_3 = tmp;
p_regs->sw147.ref_invd_cur_3 = 512 / tmp;
}
p_regs->sw129.ref_invd_col_0 = 0;
p_regs->sw129.ref_invd_col_1 = 0;
p_regs->sw130.ref_invd_col_2 = 0;
p_regs->sw130.ref_invd_col_3 = 0;
}
}
p_regs->sw52.startmb_x = 0;
p_regs->sw52.startmb_y = 0;
p_regs->sw50.filtering_dis = p_syn->pp.loopFilterDisable;
p_regs->sw122.alpha_offset = p_syn->pp.alphaOffset;
p_regs->sw122.beta_offset = p_syn->pp.betaOffset;
p_regs->sw50.skip_mode = p_syn->pp.skipModeFlag;
p_regs->sw120.pic_refer_flag = p_syn->pp.pictureReferenceFlag;
if (p_syn->pp.picCodingType == PFRAME
|| (p_syn->pp.picCodingType == IFRAME && !p_hal->first_field)) {
p_regs->sw57.dmmv_wr_en = 1;
} else {
p_regs->sw57.dmmv_wr_en = 0;
}
//!< set mv base
p_regs->sw62.dmmv_st_adr = mpp_buffer_get_fd(p_hal->mv_buf);
if (p_hal->first_field ||
(p_syn->pp.picCodingType == BFRAME && p_hal->prev_pic_structure)) {
} else {
RK_U32 frame_width = 0, frame_height = 0, offset = 0;
frame_width = (p_syn->pp.horizontalSize + 15) >> 4;
if (p_syn->pp.progressiveFrame)
frame_height = (p_syn->pp.verticalSize + 15) >> 4;
else
frame_height = 2 * ((p_syn->pp.verticalSize + 31) >> 5);
offset = MPP_ALIGN(frame_width * frame_height / 2, 2) * 16;
mpp_dev_set_reg_offset(p_hal->dev, 62, offset);
}
{
RK_U32 pic_type = 0;
RK_U32 prev_anc_type = 0;
if (p_hal->work0 >= 0) {
pic_type = p_hal->pic[p_hal->work0].pic_type;
}
prev_anc_type = !pic_type || (!p_hal->first_field && !p_hal->prev_pic_structure);
p_regs->sw136.prev_anc_type = prev_anc_type;
}
//!< b-picture needs to know if future reference is field or frame coded
// p_regs->sw134.refer2_field_e = (!p_hal->prev_pic_structure) ? 1 : 0;
// p_regs->sw135.refer3_field_e = (!p_hal->prev_pic_structure) ? 1 : 0;
if (!p_hal->prev_pic_structure) {
mpp_dev_set_reg_offset(p_hal->dev, 134, 2);
mpp_dev_set_reg_offset(p_hal->dev, 135, 3);
}
p_regs->sw57.dec_out_dis = 0;
p_regs->sw57.dec_e = 1;
return MPP_OK;
__FAILED:
return ret;
}
static MPP_RET update_parameters(AvsdHalCtx_t *p_hal)
{
AvsdSyntax_t *p_syn = &p_hal->syn;
if (p_syn->pp.pictureStructure == FRAMEPICTURE || !p_hal->first_field) {
p_hal->first_field = 1;
if (p_syn->pp.picCodingType != BFRAME) {
RK_S32 temp = p_hal->work1;
p_hal->work1 = p_hal->work0;
p_hal->work0 = p_hal->work_out;
p_hal->pic[p_hal->work_out].pic_type = p_syn->pp.picCodingType == IFRAME;
p_hal->work_out = temp;
p_hal->prev_pic_structure = p_syn->pp.pictureStructure;
}
p_hal->prev_pic_code_type = p_syn->pp.picCodingType;
} else {
p_hal->first_field = 0;
}
return MPP_OK;
}
static MPP_RET repeat_other_field(AvsdHalCtx_t *p_hal, HalTaskInfo *task)
{
RK_U8 i = 0;
RK_U8 *pdata = NULL;
MppBuffer mbuffer = NULL;
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdVdpu2Regs_t *p_regs = (AvsdVdpu2Regs_t *)p_hal->p_regs;
//!< re-find start code and calculate offset
p_hal->data_offset = p_regs->sw64.rlc_vlc_st_adr >> 10;
p_hal->data_offset += p_hal->syn.bitstream_offset;
p_hal->data_offset -= MPP_MIN(p_hal->data_offset, 8);
mpp_buf_slot_get_prop(p_hal->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer);
pdata = (RK_U8 *)mpp_buffer_get_ptr(mbuffer) + p_hal->data_offset;
while (i < 16) {
if (pdata[i] == 0 && pdata[i + 1] == 0 && pdata[i + 2] == 1) {
p_hal->data_offset += i;
break;
}
i++;
}
AVSD_HAL_DBG(AVSD_HAL_DBG_OFFSET, "frame_no %d idx %d offset %x\n",
p_hal->frame_no, i, p_hal->data_offset);
//!< re-generate register
FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec));
hal_avsd_vdpu2_start((void *)p_hal, task);
hal_avsd_vdpu2_wait((void *)p_hal, task);
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief
* init
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu2_init(void *decoder, MppHalCfg *cfg)
{
MPP_RET ret = MPP_ERR_UNKNOW;
RK_U32 buf_size = 0;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("AVS_vdpu2 In.");
buf_size = (1920 * 1088) * 2;
FUN_CHECK(ret = mpp_buffer_get(p_hal->buf_group, &p_hal->mv_buf, buf_size));
p_hal->p_regs = mpp_calloc_size(RK_U32, sizeof(AvsdVdpu2Regs_t));
MEM_CHECK(ret, p_hal->p_regs);
mpp_slots_set_prop(p_hal->frame_slots, SLOTS_HOR_ALIGN, avsd_hor_align);
mpp_slots_set_prop(p_hal->frame_slots, SLOTS_VER_ALIGN, avsd_ver_align);
mpp_slots_set_prop(p_hal->frame_slots, SLOTS_LEN_ALIGN, avsd_len_align);
p_hal->regs_num = 159;
//!< initial for control
p_hal->first_field = 1;
p_hal->prev_pic_structure = 0; //!< field
memset(p_hal->pic, 0, sizeof(p_hal->pic));
p_hal->work_out = -1;
p_hal->work0 = -1;
p_hal->work1 = -1;
AVSD_HAL_TRACE("Out.");
(void)cfg;
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief
* deinit
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu2_deinit(void *decoder)
{
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
if (p_hal->mv_buf) {
mpp_buffer_put(p_hal->mv_buf);
p_hal->mv_buf = NULL;
}
MPP_FREE(p_hal->p_regs);
AVSD_HAL_TRACE("Out.");
return MPP_OK;
}
/*!
***********************************************************************
* \brief
* generate register
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu2_gen_regs(void *decoder, HalTaskInfo *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
if (task->dec.flags.parse_err || task->dec.flags.ref_err) {
goto __RETURN;
}
p_hal->data_offset = p_hal->syn.bitstream_offset;
FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec));
__RETURN:
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
__FAILED:
return ret;
}
/*!
***********************************************************************
* \brief h
* start hard
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu2_start(void *decoder, HalTaskInfo *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
if (task->dec.flags.parse_err || task->dec.flags.ref_err) {
goto __RETURN;
}
do {
MppDevRegWrCfg wr_cfg;
MppDevRegRdCfg rd_cfg;
RK_U32 reg_size = 159 * sizeof(RK_U32);
wr_cfg.reg = p_hal->p_regs;
wr_cfg.size = reg_size;
wr_cfg.offset = 0;
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_REG_WR, &wr_cfg);
if (ret) {
mpp_err_f("set register write failed %d\n", ret);
break;
}
rd_cfg.reg = p_hal->p_regs;
rd_cfg.size = reg_size;
rd_cfg.offset = 0;
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_REG_RD, &rd_cfg);
if (ret) {
mpp_err_f("set register read failed %d\n", ret);
break;
}
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_CMD_SEND, NULL);
if (ret) {
mpp_err_f("send cmd failed %d\n", ret);
break;
}
} while (0);
__RETURN:
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}
/*!
***********************************************************************
* \brief
* wait hard
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu2_wait(void *decoder, HalTaskInfo *task)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
if (task->dec.flags.parse_err || task->dec.flags.ref_err) {
goto __SKIP_HARD;
}
ret = mpp_dev_ioctl(p_hal->dev, MPP_DEV_CMD_POLL, NULL);
if (ret)
mpp_err_f("poll cmd failed %d\n", ret);
__SKIP_HARD:
if (p_hal->dec_cb) {
DecCbHalDone param;
param.task = (void *)&task->dec;
param.regs = (RK_U32 *)p_hal->p_regs;
if (!((AvsdVdpu2Regs_t *)p_hal->p_regs)->sw55.dec_rdy_sts) {
param.hard_err = 1;
} else
param.hard_err = 0;
mpp_callback(p_hal->dec_cb, &param);
AVSD_HAL_DBG(AVSD_HAL_DBG_WAIT, "reg[55]=%08x, ref=%d, dpberr=%d, harderr=%d\n",
p_hal->p_regs[55], task->dec.flags.used_for_ref, task->dec.flags.ref_err, param.hard_err);
}
update_parameters(p_hal);
memset(&p_hal->p_regs[55], 0, sizeof(RK_U32));
if (!p_hal->first_field && p_hal->syn.pp.pictureStructure == FIELDPICTURE &&
!task->dec.flags.parse_err && !task->dec.flags.ref_err) {
repeat_other_field(p_hal, task);
}
p_hal->frame_no++;
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}
/*!
***********************************************************************
* \brief
* reset
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu2_reset(void *decoder)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder;
AVSD_HAL_TRACE("In.");
p_hal->first_field = 1;
p_hal->prev_pic_structure = 0; //!< field
memset(p_hal->pic, 0, sizeof(p_hal->pic));
p_hal->work_out = -1;
p_hal->work0 = -1;
p_hal->work1 = -1;
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}
/*!
***********************************************************************
* \brief
* flush
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu2_flush(void *decoder)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AVSD_HAL_TRACE("In.");
(void)decoder;
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}
/*!
***********************************************************************
* \brief
* control
***********************************************************************
*/
//extern "C"
MPP_RET hal_avsd_vdpu2_control(void *decoder, MpiCmd cmd_type, void *param)
{
MPP_RET ret = MPP_ERR_UNKNOW;
AVSD_HAL_TRACE("In.");
(void)decoder;
(void)cmd_type;
(void)param;
AVSD_HAL_TRACE("Out.");
return ret = MPP_OK;
}

View File

@@ -0,0 +1,39 @@
/*
* 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_AVSD_VDPU2_H__
#define __HAL_AVSD_VDPU2_H__
#include "mpp_hal.h"
#ifdef __cplusplus
extern "C" {
#endif
MPP_RET hal_avsd_vdpu2_init (void *decoder, MppHalCfg *cfg);
MPP_RET hal_avsd_vdpu2_deinit (void *decoder);
MPP_RET hal_avsd_vdpu2_gen_regs(void *decoder, HalTaskInfo *task);
MPP_RET hal_avsd_vdpu2_start (void *decoder, HalTaskInfo *task);
MPP_RET hal_avsd_vdpu2_wait (void *decoder, HalTaskInfo *task);
MPP_RET hal_avsd_vdpu2_reset (void *decoder);
MPP_RET hal_avsd_vdpu2_flush (void *decoder);
MPP_RET hal_avsd_vdpu2_control (void *decoder, MpiCmd cmd_type, void *param);
#ifdef __cplusplus
}
#endif
#endif /*__HAL_AVSD_VDPU2_H__*/

View File

@@ -0,0 +1,230 @@
/*
* 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_AVSD_VDPU2_REG_H__
#define __HAL_AVSD_VDPU2_REG_H__
typedef struct {
RK_U32 sw00_49[50];
struct {
RK_U32 dec_tiled_msb : 1;
RK_U32 adtion_latency : 6;
RK_U32 dec_fixed_quant : 1;
RK_U32 filtering_dis : 1;
RK_U32 skip_mode : 1;
RK_U32 dec_ascmd0_dis : 1;
RK_U32 adv_pref_dis : 1;
RK_U32 dec_tiled_lsb : 1;
RK_U32 refbuf_thrd : 12;
RK_U32 refbuf_pid : 5;
RK_U32 reverse0 : 2;
} sw50;
struct {
RK_U32 stream_len : 24;
RK_U32 stream_len_ext : 1;
RK_U32 init_qp : 6;
RK_U32 reverse0 : 1;
} sw51;
struct {
RK_U32 startmb_y : 8;
RK_U32 startmb_x : 9;
RK_U32 adv_pref_thrd : 14;
RK_U32 reverse0 : 1;
} sw52;
struct {
RK_U32 dec_fmt_sel : 4;
RK_U32 reverse0 : 28;
} sw53;
struct {
RK_U32 dec_in_endian : 1;
RK_U32 dec_out_endian : 1;
RK_U32 dec_in_wordsp : 1;
RK_U32 dec_out_wordsp : 1;
RK_U32 dec_strm_wordsp : 1;
RK_U32 dec_strendian_e : 1;
RK_U32 reverse0 : 26;
} sw54;
struct {
RK_U32 dec_irq : 1;
RK_U32 dec_irq_dis : 1;
RK_U32 reverse0 : 2;
RK_U32 dec_rdy_sts : 1;
RK_U32 pp_bus_sts : 1;
RK_U32 buf_emt_sts : 1;
RK_U32 reverse1 : 1;
RK_U32 aso_det_sts : 1;
RK_U32 slice_det_sts : 1;
RK_U32 bslice_det_sts : 1;
RK_U32 reverse2 : 1;
RK_U32 error_det_sts : 1;
RK_U32 timeout_det_sts : 1;
RK_U32 reverse3 : 18;
} sw55;
struct {
RK_U32 dec_axi_id_rd : 8;
RK_U32 dec_axi_id_wr : 8;
RK_U32 dec_max_burlen : 5;
RK_U32 bus_pos_sel : 1;
RK_U32 dec_data_discd_en : 1;
RK_U32 axi_sel : 1;
RK_U32 reverse0 : 8;
} sw56;
struct {
RK_U32 dec_e : 1;
RK_U32 refpic_buf2_en : 1;
RK_U32 dec_out_dis : 1;
RK_U32 reverse0 : 1;
RK_U32 dec_clkgate_en : 1;
RK_U32 timeout_sts_en : 1;
RK_U32 rd_cnt_tab_en : 1;
RK_U32 reverse1 : 1;
RK_U32 first_reftop_en : 1;
RK_U32 reftop_en : 1;
RK_U32 dmmv_wr_en : 1;
RK_U32 reverse2 : 1;
RK_U32 fwd_interlace_e : 1;
RK_U32 pic_topfield_e : 1;
RK_U32 pic_inter_e : 1;
RK_U32 pic_b_e : 1;
RK_U32 pic_fieldmode_e : 1;
RK_U32 pic_interlace_e : 1;
RK_U32 reverse3 : 2;
RK_U32 rlc_mode_en : 1;
RK_U32 addit_ch_fmt_wen : 1;
RK_U32 st_code_exit : 1;
RK_U32 reverse4 : 2;
RK_U32 inter_dblspeed : 1;
RK_U32 intra_dblspeed : 1;
RK_U32 intra_dbl3t : 1;
RK_U32 pref_sigchan : 1;
RK_U32 cache_en : 1;
RK_U32 reverse5 : 1;
RK_U32 dec_timeout_mode : 1;
} sw57;
RK_U32 sw58;
struct {
RK_U32 reserve : 2;
RK_S32 pred_bc_tap_0_2 : 10;
RK_S32 pred_bc_tap_0_1 : 10;
RK_S32 pred_bc_tap_0_0 : 10;
} sw59;
RK_U32 sw60;
RK_U32 sw61;
struct {
RK_U32 dmmv_st_adr : 32;
} sw62;
struct {
RK_U32 dec_out_st_adr : 32;
} sw63;
struct {
RK_U32 rlc_vlc_st_adr : 32;
} sw64;
RK_U32 sw65_119[55];
struct {
RK_U32 pic_refer_flag : 1;
RK_U32 reserver0 : 6;
RK_U32 mb_height_off : 4;
RK_U32 pic_mb_height_p : 8;
RK_U32 mb_width_off : 4;
RK_U32 pic_mb_width : 9;
} sw120;
struct {
RK_U32 reserve0 : 25;
RK_U32 avs_h_ext : 1;
RK_U32 reserve1 : 6;
} sw121;
struct {
RK_U32 beta_offset : 5;
RK_U32 alpha_offset : 5;
RK_U32 reserver0 : 16;
RK_U32 strm_start_bit : 6;
} sw122;
RK_U32 sw123_128[6];
struct {
RK_U32 ref_invd_col_0 : 16;
RK_U32 ref_invd_col_1 : 16;
} sw129;
struct {
RK_U32 ref_invd_col_2 : 16;
RK_U32 ref_invd_col_3 : 16;
} sw130;
union {
RK_U32 refer0_base : 32;
struct { //!< left move 10bit
RK_U32 refer0_topc_e : 1;
RK_U32 refer0_field_e : 1;
};
} sw131;
struct {
RK_U32 ref_dist_cur_0 : 16;
RK_U32 ref_dist_cur_1 : 16;
} sw132;
struct {
RK_U32 ref_dist_cur_2 : 16;
RK_U32 ref_dist_cur_3 : 16;
} sw133;
union {
RK_U32 refer2_base : 32;
struct { //!< left move 10bit
RK_U32 refer2_topc_e : 1;
RK_U32 refer2_field_e : 1;
};
} sw134;
union {
RK_U32 refer3_base : 32;
struct { //!< left move 10bit
RK_U32 refer3_topc_e : 1;
RK_U32 refer3_field_e : 1;
};
} sw135;
struct {
RK_U32 prev_anc_type : 1;
RK_U32 reserver0 : 31;
} sw136;
RK_U32 sw137_145[9];
struct {
RK_U32 ref_invd_cur_0 : 16;
RK_U32 ref_invd_cur_1 : 16;
} sw146;
struct {
RK_U32 ref_invd_cur_2 : 16;
RK_U32 ref_invd_cur_3 : 16;
} sw147;
union {
RK_U32 refer1_base : 32;
struct { //!< left move 10bit
RK_U32 refer1_topc_e : 1;
RK_U32 refer1_field_e : 1;
};
} sw148;
RK_U32 sw149_152[4];
struct {
RK_U32 reserve : 2;
RK_U32 pred_bc_tap_1_1 : 10;
RK_U32 pred_bc_tap_1_0 : 10;
RK_U32 pred_bc_tap_0_3 : 10;
} sw153;
struct {
RK_U32 reserve : 2;
RK_U32 pred_bc_tap_2_0 : 10;
RK_U32 pred_bc_tap_1_3 : 10;
RK_U32 pred_bc_tap_1_2 : 10;
} sw154;
RK_U32 sw155_158[4];
} AvsdVdpu2Regs_t;
#endif /*__HAL_AVSD_VDPU2_REG_H__*/

View File

@@ -256,7 +256,7 @@ MPP_RET hal_jpegd_rkv_init(void *hal, MppHalCfg *cfg)
ret = mpp_dev_init(&ctx->dev, ctx->dev_type);
if (ret) {
mpp_err("mpp_device_init failed. ret: %d\n", ret);
mpp_err("mpp_dev_init failed. ret: %d\n", ret);
return ret;
}

View File

@@ -134,8 +134,8 @@ int VPUClientInit(VPU_CLIENT_TYPE type)
ctx_type = MPP_CTX_DEC;
type = VPU_DEC;
break;
case VPU_DEC_AVS:
coding = MPP_VIDEO_CodingAVS;
case VPU_DEC_AVSPLUS:
coding = MPP_VIDEO_CodingAVSPLUS;
ctx_type = MPP_CTX_DEC;
type = VPU_DEC;
break;

View File

@@ -60,6 +60,7 @@ static MppCodingTypeInfo support_list[] = {
{ MPP_CTX_DEC, MPP_VIDEO_CodingVP9, "dec", "VP9", },
#endif
#if HAVE_AVSD
{ MPP_CTX_DEC, MPP_VIDEO_CodingAVS, "dec", "avs", },
{ MPP_CTX_DEC, MPP_VIDEO_CodingAVSPLUS, "dec", "avs+", },
#endif
#if HAVE_AVS2D

View File

@@ -49,7 +49,7 @@
#define HAVE_AVS2 ((RK_U32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingAVS2))))
#define HAVE_AV1 ((RK_U32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingAV1))))
#define CAP_CODING_VDPU (HAVE_MPEG2|HAVE_H263|HAVE_MPEG4|HAVE_AVC|HAVE_MJPEG|HAVE_VP8)
#define CAP_CODING_VDPU (HAVE_MPEG2|HAVE_H263|HAVE_MPEG4|HAVE_AVC|HAVE_MJPEG|HAVE_VP8|HAVE_AVS)
#define CAP_CODING_JPEGD_PP (HAVE_MJPEG)
#define CAP_CODING_AVSD (HAVE_AVS)
#define CAP_CODING_AVSPD (HAVE_AVSP)
@@ -303,23 +303,6 @@ static const MppDecHwCap vdpu38x = {
.reserved = 0,
};
static const MppDecHwCap avsd = {
.cap_coding = CAP_CODING_AVSD,
.type = VPU_CLIENT_AVSPLUS_DEC,
.cap_fbc = 0,
.cap_4k = 0,
.cap_8k = 0,
.cap_colmv_buf = 0,
.cap_hw_h265_rps = 0,
.cap_hw_vp9_prob = 0,
.cap_jpg_pp_out = 0,
.cap_10bit = 0,
.cap_down_scale = 0,
.cap_lmt_linebuf = 1,
.cap_core_num = 1,
.reserved = 0,
};
static const MppDecHwCap avspd = {
.cap_coding = CAP_CODING_AVSPD,
.type = VPU_CLIENT_AVSPLUS_DEC,
@@ -582,7 +565,7 @@ static const MppSocInfo mpp_soc_infos[] = {
"rk3228h",
ROCKCHIP_SOC_RK3228H,
HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_RKVDEC | HAVE_AVSDEC | HAVE_VEPU22,
{ &vdpu341_lite, &vdpu2, &vdpu2_jpeg_pp, &avsd, NULL, NULL, },
{ &vdpu341_lite, &vdpu2, &vdpu2_jpeg_pp, &avspd, NULL, NULL, },
{ &vepu2_no_jpeg, &vepu22, NULL, NULL, },
},
{ /*

View File

@@ -86,8 +86,8 @@ int main()
dev = mpp_get_vcodec_dev_name(MPP_CTX_DEC, MPP_VIDEO_CodingVP9);
mpp_log("VP9 decoder: %s\n", dev);
dev = mpp_get_vcodec_dev_name(MPP_CTX_DEC, MPP_VIDEO_CodingAVS);
mpp_log("avs decoder: %s\n", dev);
dev = mpp_get_vcodec_dev_name(MPP_CTX_DEC, MPP_VIDEO_CodingAVSPLUS);
mpp_log("avs+ decoder: %s\n", dev);
mpp_log("\n");
mpp_log("start probing encoder device name:\n");