mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-10-05 01:02:39 +08:00
feat[dec_test]: Add buffer mode option
Add an option in dec_test to demo zero-copy external buffers mode. use -bufmode to config the buffer mode option hl - half internal mode i - pure internal mode e - pure external mode Change-Id: Ib92c30acd8c370843becb286c935de056b09bcbd Signed-off-by: Yanjun Liao <yanjun.liao@rock-chips.com> Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
This commit is contained in:
@@ -678,10 +678,8 @@ MPP_RET mpp_buffer_group_reset(MppBufferGroupImpl *p)
|
|||||||
MPP_RET mpp_buffer_group_set_callback(MppBufferGroupImpl *p,
|
MPP_RET mpp_buffer_group_set_callback(MppBufferGroupImpl *p,
|
||||||
MppBufCallback callback, void *arg)
|
MppBufCallback callback, void *arg)
|
||||||
{
|
{
|
||||||
if (NULL == p) {
|
if (!p)
|
||||||
mpp_err_f("found NULL pointer\n");
|
return MPP_OK;
|
||||||
return MPP_ERR_NULL_PTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
MPP_BUF_FUNCTION_ENTER();
|
MPP_BUF_FUNCTION_ENTER();
|
||||||
|
|
||||||
|
@@ -153,7 +153,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
MppBufferGroup mPacketGroup;
|
MppBufferGroup mPacketGroup;
|
||||||
MppBufferGroup mFrameGroup;
|
MppBufferGroup mFrameGroup;
|
||||||
RK_U32 mExternalFrameGroup;
|
RK_U32 mExternalBufferMode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mpp task queue for advance task mode
|
* Mpp task queue for advance task mode
|
||||||
|
78
mpp/mpp.cpp
78
mpp/mpp.cpp
@@ -88,7 +88,7 @@ Mpp::Mpp(MppCtx ctx)
|
|||||||
mTaskGetCount(0),
|
mTaskGetCount(0),
|
||||||
mPacketGroup(NULL),
|
mPacketGroup(NULL),
|
||||||
mFrameGroup(NULL),
|
mFrameGroup(NULL),
|
||||||
mExternalFrameGroup(0),
|
mExternalBufferMode(0),
|
||||||
mUsrInPort(NULL),
|
mUsrInPort(NULL),
|
||||||
mUsrOutPort(NULL),
|
mUsrOutPort(NULL),
|
||||||
mMppInPort(NULL),
|
mMppInPort(NULL),
|
||||||
@@ -327,7 +327,7 @@ void Mpp::clear()
|
|||||||
mPacketGroup = NULL;
|
mPacketGroup = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFrameGroup && !mExternalFrameGroup) {
|
if (mFrameGroup && !mExternalBufferMode) {
|
||||||
mpp_buffer_group_put(mFrameGroup);
|
mpp_buffer_group_put(mFrameGroup);
|
||||||
mFrameGroup = NULL;
|
mFrameGroup = NULL;
|
||||||
}
|
}
|
||||||
@@ -1173,32 +1173,60 @@ MPP_RET Mpp::control_dec(MpiCmd cmd, MppParam param)
|
|||||||
ret = mpp_dec_control(mDec, cmd, param);
|
ret = mpp_dec_control(mDec, cmd, param);
|
||||||
} break;
|
} break;
|
||||||
case MPP_DEC_SET_EXT_BUF_GROUP: {
|
case MPP_DEC_SET_EXT_BUF_GROUP: {
|
||||||
mFrameGroup = (MppBufferGroup)param;
|
/*
|
||||||
if (param) {
|
* NOTE: If frame buffer group is configured before decoder init
|
||||||
mExternalFrameGroup = 1;
|
* then the buffer limitation maybe not be correctly setup
|
||||||
|
* without infomation from InfoChange frame.
|
||||||
|
* And the thread signal connection may not be setup here. It
|
||||||
|
* may have a bad effect on MPP efficiency.
|
||||||
|
*/
|
||||||
|
if (!mInitDone) {
|
||||||
|
mpp_err("WARNING: setup buffer group before decoder init\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = MPP_OK;
|
||||||
|
if (!param) {
|
||||||
|
/* set to internal mode */
|
||||||
|
if (mExternalBufferMode) {
|
||||||
|
/* switch from external mode to internal mode */
|
||||||
|
mpp_assert(mFrameGroup);
|
||||||
|
mpp_buffer_group_set_callback((MppBufferGroupImpl *)mFrameGroup,
|
||||||
|
NULL, NULL);
|
||||||
|
mFrameGroup = NULL;
|
||||||
|
} else {
|
||||||
|
/* keep internal buffer mode cleanup old buffers */
|
||||||
|
if (mFrameGroup)
|
||||||
|
mpp_buffer_group_clear(mFrameGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpp_dbg_info("using internal buffer group %p\n", mFrameGroup);
|
||||||
|
mExternalBufferMode = 0;
|
||||||
|
} else {
|
||||||
|
/* set to external mode */
|
||||||
|
if (mExternalBufferMode) {
|
||||||
|
/* keep external buffer mode */
|
||||||
|
if (mFrameGroup != param) {
|
||||||
|
/* switch to new buffer group */
|
||||||
|
mpp_assert(mFrameGroup);
|
||||||
|
mpp_buffer_group_set_callback((MppBufferGroupImpl *)mFrameGroup,
|
||||||
|
NULL, NULL);
|
||||||
|
} else {
|
||||||
|
/* keep old group the external group user should cleanup its old buffers */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* switch from intenal mode to external mode */
|
||||||
|
if (mFrameGroup)
|
||||||
|
mpp_buffer_group_put(mFrameGroup);
|
||||||
|
}
|
||||||
|
|
||||||
mpp_dbg_info("using external buffer group %p\n", mFrameGroup);
|
mpp_dbg_info("using external buffer group %p\n", mFrameGroup);
|
||||||
|
|
||||||
if (mInitDone) {
|
mFrameGroup = (MppBufferGroup)param;
|
||||||
ret = mpp_buffer_group_set_callback((MppBufferGroupImpl *)param,
|
mpp_buffer_group_set_callback((MppBufferGroupImpl *)mFrameGroup,
|
||||||
mpp_notify_by_buffer_group,
|
mpp_notify_by_buffer_group, (void *)this);
|
||||||
(void *)this);
|
mExternalBufferMode = 1;
|
||||||
|
notify(MPP_DEC_NOTIFY_EXT_BUF_GRP_READY);
|
||||||
notify(MPP_DEC_NOTIFY_EXT_BUF_GRP_READY);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* NOTE: If frame buffer group is configured before decoder init
|
|
||||||
* then the buffer limitation maybe not be correctly setup
|
|
||||||
* without infomation from InfoChange frame.
|
|
||||||
* And the thread signal connection may not be setup here. It
|
|
||||||
* may have a bad effect on MPP efficiency.
|
|
||||||
*/
|
|
||||||
mpp_err("WARNING: setup buffer group before decoder init\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* The buffer group should be destroyed before */
|
|
||||||
mExternalFrameGroup = 0;
|
|
||||||
ret = MPP_OK;
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case MPP_DEC_SET_INFO_CHANGE_READY: {
|
case MPP_DEC_SET_INFO_CHANGE_READY: {
|
||||||
|
@@ -43,6 +43,7 @@ typedef struct {
|
|||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
/* input and output */
|
/* input and output */
|
||||||
|
DecBufMgr buf_mgr;
|
||||||
MppBufferGroup frm_grp;
|
MppBufferGroup frm_grp;
|
||||||
MppPacket packet;
|
MppPacket packet;
|
||||||
size_t packet_size;
|
size_t packet_size;
|
||||||
@@ -147,40 +148,20 @@ void *thread_output(void *arg)
|
|||||||
RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
|
RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
|
||||||
RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
|
RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
|
||||||
RK_U32 buf_size = mpp_frame_get_buf_size(frame);
|
RK_U32 buf_size = mpp_frame_get_buf_size(frame);
|
||||||
|
MppBufferGroup grp = NULL;
|
||||||
|
|
||||||
mpp_log_q(quiet, "decode_get_frame get info changed found\n");
|
mpp_log_q(quiet, "decode_get_frame get info changed found\n");
|
||||||
mpp_log_q(quiet, "decoder require buffer w:h [%d:%d] stride [%d:%d] size %d\n",
|
mpp_log_q(quiet, "decoder require buffer w:h [%d:%d] stride [%d:%d] size %d\n",
|
||||||
width, height, hor_stride, ver_stride, buf_size);
|
width, height, hor_stride, ver_stride, buf_size);
|
||||||
|
|
||||||
if (NULL == data->frm_grp) {
|
grp = dec_buf_mgr_setup(data->buf_mgr, buf_size, 24, cmd->buf_mode);
|
||||||
/* If buffer group is not set create one and limit it */
|
/* Set buffer to mpp decoder */
|
||||||
ret = mpp_buffer_group_get_internal(&data->frm_grp, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE);
|
ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, grp);
|
||||||
if (ret) {
|
|
||||||
mpp_err("get mpp buffer group failed ret %d\n", ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set buffer to mpp decoder */
|
|
||||||
ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, data->frm_grp);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("set buffer group failed ret %d\n", ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* If old buffer group exist clear it */
|
|
||||||
ret = mpp_buffer_group_clear(data->frm_grp);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("clear buffer group failed ret %d\n", ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use limit config to limit buffer count to 24 */
|
|
||||||
ret = mpp_buffer_group_limit_config(data->frm_grp, buf_size, 24);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mpp_err("limit buffer group failed ret %d\n", ret);
|
mpp_err("%p set buffer group failed ret %d\n", ctx, ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
data->frm_grp = grp;
|
||||||
|
|
||||||
ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
|
ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -271,6 +252,12 @@ int mt_dec_decode(MpiDecTestCmd *cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = dec_buf_mgr_init(&data.buf_mgr);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("dec_buf_mgr_init failed\n");
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
ret = mpp_packet_init(&packet, NULL, 0);
|
ret = mpp_packet_init(&packet, NULL, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mpp_err("mpp_packet_init failed\n");
|
mpp_err("mpp_packet_init failed\n");
|
||||||
@@ -396,9 +383,10 @@ MPP_TEST_OUT:
|
|||||||
ctx = NULL;
|
ctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.frm_grp) {
|
data.frm_grp = NULL;
|
||||||
mpp_buffer_group_put(data.frm_grp);
|
if (data.buf_mgr) {
|
||||||
data.frm_grp = NULL;
|
dec_buf_mgr_deinit(data.buf_mgr);
|
||||||
|
data.buf_mgr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.fp_output) {
|
if (data.fp_output) {
|
||||||
|
@@ -42,6 +42,7 @@ typedef struct {
|
|||||||
RK_U32 loop_end;
|
RK_U32 loop_end;
|
||||||
|
|
||||||
/* input and output */
|
/* input and output */
|
||||||
|
DecBufMgr buf_mgr;
|
||||||
MppBufferGroup frm_grp;
|
MppBufferGroup frm_grp;
|
||||||
MppPacket packet;
|
MppPacket packet;
|
||||||
MppFrame frame;
|
MppFrame frame;
|
||||||
@@ -151,40 +152,20 @@ static int multi_dec_simple(MpiDecMultiCtx *data)
|
|||||||
RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
|
RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
|
||||||
RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
|
RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
|
||||||
RK_U32 buf_size = mpp_frame_get_buf_size(frame);
|
RK_U32 buf_size = mpp_frame_get_buf_size(frame);
|
||||||
|
MppBufferGroup grp = NULL;
|
||||||
|
|
||||||
mpp_log_q(quiet, "decode_get_frame get info changed found\n");
|
mpp_log_q(quiet, "decode_get_frame get info changed found\n");
|
||||||
mpp_log_q(quiet, "decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d",
|
mpp_log_q(quiet, "decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d",
|
||||||
width, height, hor_stride, ver_stride, buf_size);
|
width, height, hor_stride, ver_stride, buf_size);
|
||||||
|
|
||||||
if (NULL == data->frm_grp) {
|
grp = dec_buf_mgr_setup(data->buf_mgr, buf_size, 24, cmd->buf_mode);
|
||||||
/* If buffer group is not set create one and limit it */
|
/* Set buffer to mpp decoder */
|
||||||
ret = mpp_buffer_group_get_internal(&data->frm_grp, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE);
|
ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, grp);
|
||||||
if (ret) {
|
|
||||||
mpp_err("get mpp buffer group failed ret %d\n", ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set buffer to mpp decoder */
|
|
||||||
ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, data->frm_grp);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("set buffer group failed ret %d\n", ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* If old buffer group exist clear it */
|
|
||||||
ret = mpp_buffer_group_clear(data->frm_grp);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("clear buffer group failed ret %d\n", ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use limit config to limit buffer count to 24 with buf_size */
|
|
||||||
ret = mpp_buffer_group_limit_config(data->frm_grp, buf_size, 24);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mpp_err("limit buffer group failed ret %d\n", ret);
|
mpp_err("%p set buffer group failed ret %d\n", ctx, ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
data->frm_grp = grp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All buffer group config done. Set info change ready to let
|
* All buffer group config done. Set info change ready to let
|
||||||
@@ -428,6 +409,12 @@ void* multi_dec_decode(void *cmd_ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = dec_buf_mgr_init(&dec_ctx->buf_mgr);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("dec_buf_mgr_init failed\n");
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd->simple) {
|
if (cmd->simple) {
|
||||||
ret = mpp_packet_init(&packet, NULL, 0);
|
ret = mpp_packet_init(&packet, NULL, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -438,18 +425,19 @@ void* multi_dec_decode(void *cmd_ctx)
|
|||||||
RK_U32 hor_stride = MPP_ALIGN(width, 16);
|
RK_U32 hor_stride = MPP_ALIGN(width, 16);
|
||||||
RK_U32 ver_stride = MPP_ALIGN(height, 16);
|
RK_U32 ver_stride = MPP_ALIGN(height, 16);
|
||||||
|
|
||||||
ret = mpp_buffer_group_get_internal(&dec_ctx->frm_grp, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("failed to get buffer group for input frame ret %d\n", ret);
|
|
||||||
goto MPP_TEST_OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = mpp_frame_init(&frame); /* output frame */
|
ret = mpp_frame_init(&frame); /* output frame */
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mpp_err("mpp_frame_init failed\n");
|
mpp_err("mpp_frame_init failed\n");
|
||||||
goto MPP_TEST_OUT;
|
goto MPP_TEST_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dec_ctx->frm_grp = dec_buf_mgr_setup(dec_ctx->buf_mgr, hor_stride * ver_stride * 2, 4, cmd->buf_mode);
|
||||||
|
if (!dec_ctx->frm_grp) {
|
||||||
|
mpp_err("failed to get buffer group for input frame ret %d\n", ret);
|
||||||
|
ret = MPP_NOK;
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: For jpeg could have YUV420 and YUV422 the buffer should be
|
* NOTE: For jpeg could have YUV420 and YUV422 the buffer should be
|
||||||
* larger for output. And the buffer dimension should align to 16.
|
* larger for output. And the buffer dimension should align to 16.
|
||||||
@@ -563,9 +551,10 @@ MPP_TEST_OUT:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dec_ctx->frm_grp) {
|
dec_ctx->frm_grp = NULL;
|
||||||
mpp_buffer_group_put(dec_ctx->frm_grp);
|
if (dec_ctx->buf_mgr) {
|
||||||
dec_ctx->frm_grp = NULL;
|
dec_buf_mgr_deinit(dec_ctx->buf_mgr);
|
||||||
|
dec_ctx->buf_mgr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dec_ctx->fp_output) {
|
if (dec_ctx->fp_output) {
|
||||||
|
@@ -39,6 +39,7 @@ typedef struct {
|
|||||||
RK_U32 loop_end;
|
RK_U32 loop_end;
|
||||||
|
|
||||||
/* input and output */
|
/* input and output */
|
||||||
|
DecBufMgr buf_mgr;
|
||||||
MppBufferGroup frm_grp;
|
MppBufferGroup frm_grp;
|
||||||
MppPacket packet;
|
MppPacket packet;
|
||||||
MppFrame frame;
|
MppFrame frame;
|
||||||
@@ -116,101 +117,22 @@ static int dec_loop(MpiDecLoopData *data)
|
|||||||
RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
|
RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
|
||||||
RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
|
RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
|
||||||
RK_U32 buf_size = mpp_frame_get_buf_size(frame);
|
RK_U32 buf_size = mpp_frame_get_buf_size(frame);
|
||||||
|
MppBufferGroup grp = NULL;
|
||||||
|
|
||||||
mpp_log_q(quiet, "%p decode_get_frame get info changed found\n", ctx);
|
mpp_log_q(quiet, "%p decode_get_frame get info changed found\n", ctx);
|
||||||
mpp_log_q(quiet, "%p decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d",
|
mpp_log_q(quiet, "%p decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d",
|
||||||
ctx, width, height, hor_stride, ver_stride, buf_size);
|
ctx, width, height, hor_stride, ver_stride, buf_size);
|
||||||
|
|
||||||
/*
|
grp = dec_buf_mgr_setup(data->buf_mgr, buf_size, 24, cmd->buf_mode);
|
||||||
* NOTE: We can choose decoder's buffer mode here.
|
/* Set buffer to mpp decoder */
|
||||||
* There are three mode that decoder can support:
|
ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, grp);
|
||||||
*
|
|
||||||
* Mode 1: Pure internal mode
|
|
||||||
* In the mode user will NOT call MPP_DEC_SET_EXT_BUF_GROUP
|
|
||||||
* control to decoder. Only call MPP_DEC_SET_INFO_CHANGE_READY
|
|
||||||
* to let decoder go on. Then decoder will use create buffer
|
|
||||||
* internally and user need to release each frame they get.
|
|
||||||
*
|
|
||||||
* Advantage:
|
|
||||||
* Easy to use and get a demo quickly
|
|
||||||
* Disadvantage:
|
|
||||||
* 1. The buffer from decoder may not be return before
|
|
||||||
* decoder is close. So memroy leak or crash may happen.
|
|
||||||
* 2. The decoder memory usage can not be control. Decoder
|
|
||||||
* is on a free-to-run status and consume all memory it can
|
|
||||||
* get.
|
|
||||||
* 3. Difficult to implement zero-copy display path.
|
|
||||||
*
|
|
||||||
* Mode 2: Half internal mode
|
|
||||||
* This is the mode current test code using. User need to
|
|
||||||
* create MppBufferGroup according to the returned info
|
|
||||||
* change MppFrame. User can use mpp_buffer_group_limit_config
|
|
||||||
* function to limit decoder memory usage.
|
|
||||||
*
|
|
||||||
* Advantage:
|
|
||||||
* 1. Easy to use
|
|
||||||
* 2. User can release MppBufferGroup after decoder is closed.
|
|
||||||
* So memory can stay longer safely.
|
|
||||||
* 3. Can limit the memory usage by mpp_buffer_group_limit_config
|
|
||||||
* Disadvantage:
|
|
||||||
* 1. The buffer limitation is still not accurate. Memory usage
|
|
||||||
* is 100% fixed.
|
|
||||||
* 2. Also difficult to implement zero-copy display path.
|
|
||||||
*
|
|
||||||
* Mode 3: Pure external mode
|
|
||||||
* In this mode use need to create empty MppBufferGroup and
|
|
||||||
* import memory from external allocator by file handle.
|
|
||||||
* On Android surfaceflinger will create buffer. Then
|
|
||||||
* mediaserver get the file handle from surfaceflinger and
|
|
||||||
* commit to decoder's MppBufferGroup.
|
|
||||||
*
|
|
||||||
* Advantage:
|
|
||||||
* 1. Most efficient way for zero-copy display
|
|
||||||
* Disadvantage:
|
|
||||||
* 1. Difficult to learn and use.
|
|
||||||
* 2. Player work flow may limit this usage.
|
|
||||||
* 3. May need a external parser to get the correct buffer
|
|
||||||
* size for the external allocator.
|
|
||||||
*
|
|
||||||
* The required buffer size caculation:
|
|
||||||
* hor_stride * ver_stride * 3 / 2 for pixel data
|
|
||||||
* hor_stride * ver_stride / 2 for extra info
|
|
||||||
* Total hor_stride * ver_stride * 2 will be enough.
|
|
||||||
*
|
|
||||||
* For H.264/H.265 20+ buffers will be enough.
|
|
||||||
* For other codec 10 buffers will be enough.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (NULL == data->frm_grp) {
|
|
||||||
/* If buffer group is not set create one and limit it */
|
|
||||||
ret = mpp_buffer_group_get_internal(&data->frm_grp, MPP_BUFFER_TYPE_ION);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("%p get mpp buffer group failed ret %d\n", ctx, ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set buffer to mpp decoder */
|
|
||||||
ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, data->frm_grp);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("%p set buffer group failed ret %d\n", ctx, ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* If old buffer group exist clear it */
|
|
||||||
ret = mpp_buffer_group_clear(data->frm_grp);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("%p clear buffer group failed ret %d\n", ctx, ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use limit config to limit buffer count to 24 with buf_size */
|
|
||||||
ret = mpp_buffer_group_limit_config(data->frm_grp, buf_size, 24);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mpp_err("%p limit buffer group failed ret %d\n", ctx, ret);
|
mpp_err("%p set buffer group failed ret %d\n", ctx, ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data->frm_grp = grp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All buffer group config done. Set info change ready to let
|
* All buffer group config done. Set info change ready to let
|
||||||
* decoder continue decoding
|
* decoder continue decoding
|
||||||
@@ -403,6 +325,12 @@ int dec_nt_decode(MpiDecTestCmd *cmd)
|
|||||||
mpp_err("failed to open verify file %s\n", cmd->file_slt);
|
mpp_err("failed to open verify file %s\n", cmd->file_slt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = dec_buf_mgr_init(&data.buf_mgr);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("dec_buf_mgr_init failed\n");
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd->simple) {
|
if (cmd->simple) {
|
||||||
ret = mpp_packet_init(&packet, NULL, 0);
|
ret = mpp_packet_init(&packet, NULL, 0);
|
||||||
mpp_err_f("mpp_packet_init get %p\n", packet);
|
mpp_err_f("mpp_packet_init get %p\n", packet);
|
||||||
@@ -414,18 +342,18 @@ int dec_nt_decode(MpiDecTestCmd *cmd)
|
|||||||
RK_U32 hor_stride = MPP_ALIGN(width, 16);
|
RK_U32 hor_stride = MPP_ALIGN(width, 16);
|
||||||
RK_U32 ver_stride = MPP_ALIGN(height, 16);
|
RK_U32 ver_stride = MPP_ALIGN(height, 16);
|
||||||
|
|
||||||
ret = mpp_buffer_group_get_internal(&data.frm_grp, MPP_BUFFER_TYPE_ION);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("failed to get buffer group for input frame ret %d\n", ret);
|
|
||||||
goto MPP_TEST_OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = mpp_frame_init(&frame); /* output frame */
|
ret = mpp_frame_init(&frame); /* output frame */
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mpp_err("mpp_frame_init failed\n");
|
mpp_err("mpp_frame_init failed\n");
|
||||||
goto MPP_TEST_OUT;
|
goto MPP_TEST_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.frm_grp = dec_buf_mgr_setup(data.buf_mgr, hor_stride * ver_stride * 4, 4, cmd->buf_mode);
|
||||||
|
if (!data.frm_grp) {
|
||||||
|
mpp_err("failed to get buffer group for input frame ret %d\n", ret);
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: For jpeg could have YUV420 and YUV422 the buffer should be
|
* NOTE: For jpeg could have YUV420 and YUV422 the buffer should be
|
||||||
* larger for output. And the buffer dimension should align to 16.
|
* larger for output. And the buffer dimension should align to 16.
|
||||||
@@ -546,9 +474,10 @@ MPP_TEST_OUT:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.frm_grp) {
|
data.frm_grp = NULL;
|
||||||
mpp_buffer_group_put(data.frm_grp);
|
if (data.buf_mgr) {
|
||||||
data.frm_grp = NULL;
|
dec_buf_mgr_deinit(data.buf_mgr);
|
||||||
|
data.buf_mgr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.fp_output) {
|
if (data.fp_output) {
|
||||||
|
@@ -39,6 +39,7 @@ typedef struct {
|
|||||||
RK_U32 loop_end;
|
RK_U32 loop_end;
|
||||||
|
|
||||||
/* input and output */
|
/* input and output */
|
||||||
|
DecBufMgr buf_mgr;
|
||||||
MppBufferGroup frm_grp;
|
MppBufferGroup frm_grp;
|
||||||
MppPacket packet;
|
MppPacket packet;
|
||||||
MppFrame frame;
|
MppFrame frame;
|
||||||
@@ -139,100 +140,20 @@ static int dec_simple(MpiDecLoopData *data)
|
|||||||
RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
|
RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
|
||||||
RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
|
RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
|
||||||
RK_U32 buf_size = mpp_frame_get_buf_size(frame);
|
RK_U32 buf_size = mpp_frame_get_buf_size(frame);
|
||||||
|
MppBufferGroup grp = NULL;
|
||||||
|
|
||||||
mpp_log_q(quiet, "%p decode_get_frame get info changed found\n", ctx);
|
mpp_log_q(quiet, "%p decode_get_frame get info changed found\n", ctx);
|
||||||
mpp_log_q(quiet, "%p decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d",
|
mpp_log_q(quiet, "%p decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d",
|
||||||
ctx, width, height, hor_stride, ver_stride, buf_size);
|
ctx, width, height, hor_stride, ver_stride, buf_size);
|
||||||
|
|
||||||
/*
|
grp = dec_buf_mgr_setup(data->buf_mgr, buf_size, 24, cmd->buf_mode);
|
||||||
* NOTE: We can choose decoder's buffer mode here.
|
/* Set buffer to mpp decoder */
|
||||||
* There are three mode that decoder can support:
|
ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, grp);
|
||||||
*
|
|
||||||
* Mode 1: Pure internal mode
|
|
||||||
* In the mode user will NOT call MPP_DEC_SET_EXT_BUF_GROUP
|
|
||||||
* control to decoder. Only call MPP_DEC_SET_INFO_CHANGE_READY
|
|
||||||
* to let decoder go on. Then decoder will use create buffer
|
|
||||||
* internally and user need to release each frame they get.
|
|
||||||
*
|
|
||||||
* Advantage:
|
|
||||||
* Easy to use and get a demo quickly
|
|
||||||
* Disadvantage:
|
|
||||||
* 1. The buffer from decoder may not be return before
|
|
||||||
* decoder is close. So memroy leak or crash may happen.
|
|
||||||
* 2. The decoder memory usage can not be control. Decoder
|
|
||||||
* is on a free-to-run status and consume all memory it can
|
|
||||||
* get.
|
|
||||||
* 3. Difficult to implement zero-copy display path.
|
|
||||||
*
|
|
||||||
* Mode 2: Half internal mode
|
|
||||||
* This is the mode current test code using. User need to
|
|
||||||
* create MppBufferGroup according to the returned info
|
|
||||||
* change MppFrame. User can use mpp_buffer_group_limit_config
|
|
||||||
* function to limit decoder memory usage.
|
|
||||||
*
|
|
||||||
* Advantage:
|
|
||||||
* 1. Easy to use
|
|
||||||
* 2. User can release MppBufferGroup after decoder is closed.
|
|
||||||
* So memory can stay longer safely.
|
|
||||||
* 3. Can limit the memory usage by mpp_buffer_group_limit_config
|
|
||||||
* Disadvantage:
|
|
||||||
* 1. The buffer limitation is still not accurate. Memory usage
|
|
||||||
* is 100% fixed.
|
|
||||||
* 2. Also difficult to implement zero-copy display path.
|
|
||||||
*
|
|
||||||
* Mode 3: Pure external mode
|
|
||||||
* In this mode use need to create empty MppBufferGroup and
|
|
||||||
* import memory from external allocator by file handle.
|
|
||||||
* On Android surfaceflinger will create buffer. Then
|
|
||||||
* mediaserver get the file handle from surfaceflinger and
|
|
||||||
* commit to decoder's MppBufferGroup.
|
|
||||||
*
|
|
||||||
* Advantage:
|
|
||||||
* 1. Most efficient way for zero-copy display
|
|
||||||
* Disadvantage:
|
|
||||||
* 1. Difficult to learn and use.
|
|
||||||
* 2. Player work flow may limit this usage.
|
|
||||||
* 3. May need a external parser to get the correct buffer
|
|
||||||
* size for the external allocator.
|
|
||||||
*
|
|
||||||
* The required buffer size caculation:
|
|
||||||
* hor_stride * ver_stride * 3 / 2 for pixel data
|
|
||||||
* hor_stride * ver_stride / 2 for extra info
|
|
||||||
* Total hor_stride * ver_stride * 2 will be enough.
|
|
||||||
*
|
|
||||||
* For H.264/H.265 20+ buffers will be enough.
|
|
||||||
* For other codec 10 buffers will be enough.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (NULL == data->frm_grp) {
|
|
||||||
/* If buffer group is not set create one and limit it */
|
|
||||||
ret = mpp_buffer_group_get_internal(&data->frm_grp, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("%p get mpp buffer group failed ret %d\n", ctx, ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set buffer to mpp decoder */
|
|
||||||
ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, data->frm_grp);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("%p set buffer group failed ret %d\n", ctx, ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* If old buffer group exist clear it */
|
|
||||||
ret = mpp_buffer_group_clear(data->frm_grp);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("%p clear buffer group failed ret %d\n", ctx, ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use limit config to limit buffer count to 24 with buf_size */
|
|
||||||
ret = mpp_buffer_group_limit_config(data->frm_grp, buf_size, 24);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mpp_err("%p limit buffer group failed ret %d\n", ctx, ret);
|
mpp_err("%p set buffer group failed ret %d\n", ctx, ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
data->frm_grp = grp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All buffer group config done. Set info change ready to let
|
* All buffer group config done. Set info change ready to let
|
||||||
@@ -570,6 +491,12 @@ int dec_decode(MpiDecTestCmd *cmd)
|
|||||||
mpp_err("failed to open verify file %s\n", cmd->file_slt);
|
mpp_err("failed to open verify file %s\n", cmd->file_slt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = dec_buf_mgr_init(&data.buf_mgr);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err("dec_buf_mgr_init failed\n");
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd->simple) {
|
if (cmd->simple) {
|
||||||
ret = mpp_packet_init(&packet, NULL, 0);
|
ret = mpp_packet_init(&packet, NULL, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -580,18 +507,19 @@ int dec_decode(MpiDecTestCmd *cmd)
|
|||||||
RK_U32 hor_stride = MPP_ALIGN(width, 16);
|
RK_U32 hor_stride = MPP_ALIGN(width, 16);
|
||||||
RK_U32 ver_stride = MPP_ALIGN(height, 16);
|
RK_U32 ver_stride = MPP_ALIGN(height, 16);
|
||||||
|
|
||||||
ret = mpp_buffer_group_get_internal(&data.frm_grp, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE);
|
|
||||||
if (ret) {
|
|
||||||
mpp_err("failed to get buffer group for input frame ret %d\n", ret);
|
|
||||||
goto MPP_TEST_OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = mpp_frame_init(&frame); /* output frame */
|
ret = mpp_frame_init(&frame); /* output frame */
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mpp_err("mpp_frame_init failed\n");
|
mpp_err("mpp_frame_init failed\n");
|
||||||
goto MPP_TEST_OUT;
|
goto MPP_TEST_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.frm_grp = dec_buf_mgr_setup(data.buf_mgr, hor_stride * ver_stride * 4, 4, cmd->buf_mode);
|
||||||
|
if (!data.frm_grp) {
|
||||||
|
mpp_err("failed to get buffer group for input frame ret %d\n", ret);
|
||||||
|
ret = MPP_NOK;
|
||||||
|
goto MPP_TEST_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: For jpeg could have YUV420 and YUV422 the buffer should be
|
* NOTE: For jpeg could have YUV420 and YUV422 the buffer should be
|
||||||
* larger for output. And the buffer dimension should align to 16.
|
* larger for output. And the buffer dimension should align to 16.
|
||||||
@@ -710,9 +638,10 @@ MPP_TEST_OUT:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.frm_grp) {
|
data.frm_grp = NULL;
|
||||||
mpp_buffer_group_put(data.frm_grp);
|
if (data.buf_mgr) {
|
||||||
data.frm_grp = NULL;
|
dec_buf_mgr_deinit(data.buf_mgr);
|
||||||
|
data.buf_mgr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.fp_output) {
|
if (data.fp_output) {
|
||||||
|
@@ -71,23 +71,15 @@ typedef struct FileReader_t {
|
|||||||
FileBufSlot **slots;
|
FileBufSlot **slots;
|
||||||
} FileReaderImpl;
|
} FileReaderImpl;
|
||||||
|
|
||||||
#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var))))
|
typedef struct DecBufMgrImpl_t {
|
||||||
|
MppDecBufMode buf_mode;
|
||||||
|
RK_U32 buf_count;
|
||||||
|
RK_U32 buf_size;
|
||||||
|
MppBufferGroup group;
|
||||||
|
MppBuffer *bufs;
|
||||||
|
} DecBufMgrImpl;
|
||||||
|
|
||||||
OptionInfo mpi_dec_cmd[] = {
|
#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var))))
|
||||||
{"i", "input_file", "input bitstream file"},
|
|
||||||
{"o", "output_file", "output bitstream file, "},
|
|
||||||
{"c", "ops_file", "input operation config file"},
|
|
||||||
{"w", "width", "the width of input bitstream"},
|
|
||||||
{"h", "height", "the height of input bitstream"},
|
|
||||||
{"t", "type", "input stream coding type"},
|
|
||||||
{"f", "format", "output frame format type"},
|
|
||||||
{"x", "timeout", "output timeout interval"},
|
|
||||||
{"n", "frame_number", "max output frame number"},
|
|
||||||
{"s", "instance_nb", "number of instances"},
|
|
||||||
{"v", "trace", "q - quiet f - show fps"},
|
|
||||||
{"c", "verify_file", "verify file for slt check"},
|
|
||||||
{NULL, NULL, NULL},
|
|
||||||
};
|
|
||||||
|
|
||||||
static MPP_RET add_new_slot(FileReaderImpl* impl, FileBufSlot *slot)
|
static MPP_RET add_new_slot(FileReaderImpl* impl, FileBufSlot *slot)
|
||||||
{
|
{
|
||||||
@@ -600,6 +592,29 @@ RK_S32 mpi_dec_opt_slt(void *ctx, const char *next)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RK_S32 mpi_dec_opt_bufmode(void *ctx, const char *next)
|
||||||
|
{
|
||||||
|
MpiDecTestCmd *cmd = (MpiDecTestCmd *)ctx;
|
||||||
|
|
||||||
|
if (next) {
|
||||||
|
if (strstr(next, "hi")) {
|
||||||
|
cmd->buf_mode = MPP_DEC_BUF_HALF_INT;
|
||||||
|
} else if (strstr(next, "i")) {
|
||||||
|
cmd->buf_mode = MPP_DEC_BUF_INTERNAL;
|
||||||
|
} else if (strstr(next, "e")) {
|
||||||
|
cmd->buf_mode = MPP_DEC_BUF_EXTERNAL;
|
||||||
|
} else {
|
||||||
|
cmd->buf_mode = MPP_DEC_BUF_HALF_INT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpp_err("invalid ext buf mode value\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RK_S32 mpi_dec_opt_help(void *ctx, const char *next)
|
RK_S32 mpi_dec_opt_help(void *ctx, const char *next)
|
||||||
{
|
{
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
@@ -620,6 +635,7 @@ static MppOptInfo dec_opts[] = {
|
|||||||
{"v", "trace option", "q - quiet f - show fps", mpi_dec_opt_v},
|
{"v", "trace option", "q - quiet f - show fps", mpi_dec_opt_v},
|
||||||
{"slt", "slt file", "slt verify data file", mpi_dec_opt_slt},
|
{"slt", "slt file", "slt verify data file", mpi_dec_opt_slt},
|
||||||
{"help", "help", "show help", mpi_dec_opt_help},
|
{"help", "help", "show help", mpi_dec_opt_help},
|
||||||
|
{"bufmode", "buffer mode", "hi - half internal (default) i -internal e - external", mpi_dec_opt_bufmode},
|
||||||
};
|
};
|
||||||
|
|
||||||
static RK_U32 dec_opt_cnt = MPP_ARRAY_ELEMS(dec_opts);
|
static RK_U32 dec_opt_cnt = MPP_ARRAY_ELEMS(dec_opts);
|
||||||
@@ -680,7 +696,7 @@ RK_S32 mpi_dec_test_cmd_init(MpiDecTestCmd* cmd, int argc, char **argv)
|
|||||||
|
|
||||||
mpp_opt_init(&opts);
|
mpp_opt_init(&opts);
|
||||||
/* should change node count when option increases */
|
/* should change node count when option increases */
|
||||||
mpp_opt_setup(opts, cmd, 22, dec_opt_cnt);
|
mpp_opt_setup(opts, cmd, 35, dec_opt_cnt);
|
||||||
|
|
||||||
for (i = 0; i < dec_opt_cnt; i++)
|
for (i = 0; i < dec_opt_cnt; i++)
|
||||||
mpp_opt_add(opts, &dec_opts[i]);
|
mpp_opt_add(opts, &dec_opts[i]);
|
||||||
@@ -748,3 +764,170 @@ void mpi_dec_test_cmd_options(MpiDecTestCmd* cmd)
|
|||||||
if (cmd->file_slt)
|
if (cmd->file_slt)
|
||||||
mpp_log("verify : %s\n", cmd->file_slt);
|
mpp_log("verify : %s\n", cmd->file_slt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MPP_RET dec_buf_mgr_init(DecBufMgr *mgr)
|
||||||
|
{
|
||||||
|
DecBufMgrImpl *impl = NULL;
|
||||||
|
MPP_RET ret = MPP_NOK;
|
||||||
|
|
||||||
|
if (mgr) {
|
||||||
|
impl = mpp_calloc(DecBufMgrImpl, 1);
|
||||||
|
if (impl) {
|
||||||
|
ret = MPP_OK;
|
||||||
|
} else {
|
||||||
|
mpp_err_f("failed to create decoder buffer manager\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
*mgr = impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dec_buf_mgr_deinit(DecBufMgr mgr)
|
||||||
|
{
|
||||||
|
DecBufMgrImpl *impl = (DecBufMgrImpl *)mgr;
|
||||||
|
|
||||||
|
if (NULL == impl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* release buffer group for half internal and external mode */
|
||||||
|
if (impl->group) {
|
||||||
|
mpp_buffer_group_put(impl->group);
|
||||||
|
impl->group = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release the buffers used in external mode */
|
||||||
|
if (impl->buf_count && impl->bufs) {
|
||||||
|
RK_U32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < impl->buf_count; i++) {
|
||||||
|
if (impl->bufs[i]) {
|
||||||
|
mpp_buffer_put(impl->bufs[i]);
|
||||||
|
impl->bufs[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MPP_FREE(impl->bufs);
|
||||||
|
}
|
||||||
|
|
||||||
|
MPP_FREE(impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
MppBufferGroup dec_buf_mgr_setup(DecBufMgr mgr, RK_U32 size, RK_U32 count, MppDecBufMode mode)
|
||||||
|
{
|
||||||
|
DecBufMgrImpl *impl = (DecBufMgrImpl *)mgr;
|
||||||
|
MPP_RET ret = MPP_NOK;
|
||||||
|
|
||||||
|
if (!impl)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* cleanup old buffers if previous buffer group exists */
|
||||||
|
if (impl->group) {
|
||||||
|
if (mode != impl->buf_mode) {
|
||||||
|
/* switch to different buffer mode just release old buffer group */
|
||||||
|
mpp_buffer_group_put(impl->group);
|
||||||
|
impl->group = NULL;
|
||||||
|
} else {
|
||||||
|
/* otherwise just cleanup old buffers */
|
||||||
|
mpp_buffer_group_clear(impl->group);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if there are external mode old buffers do cleanup */
|
||||||
|
if (impl->bufs) {
|
||||||
|
RK_U32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < impl->buf_count; i++) {
|
||||||
|
if (impl->bufs[i]) {
|
||||||
|
mpp_buffer_put(impl->bufs[i]);
|
||||||
|
impl->bufs[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MPP_FREE(impl->bufs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case MPP_DEC_BUF_HALF_INT : {
|
||||||
|
/* reuse previous half internal buffer group and just reconfig limit */
|
||||||
|
if (NULL == impl->group) {
|
||||||
|
ret = mpp_buffer_group_get_internal(&impl->group, MPP_BUFFER_TYPE_ION);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err_f("get mpp internal buffer group failed ret %d\n", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Use limit config to limit buffer count and buffer size */
|
||||||
|
ret = mpp_buffer_group_limit_config(impl->group, size, count);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err_f("limit buffer group failed ret %d\n", ret);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case MPP_DEC_BUF_INTERNAL : {
|
||||||
|
/* do nothing juse keep buffer group empty */
|
||||||
|
mpp_assert(NULL == impl->group);
|
||||||
|
ret = MPP_OK;
|
||||||
|
} break;
|
||||||
|
case MPP_DEC_BUF_EXTERNAL : {
|
||||||
|
RK_U32 i;
|
||||||
|
MppBufferInfo commit;
|
||||||
|
|
||||||
|
impl->bufs = mpp_calloc(MppBuffer, count);
|
||||||
|
if (!impl->bufs) {
|
||||||
|
mpp_err_f("create %d external buffer record failed\n", count);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reuse previous external buffer group */
|
||||||
|
if (NULL == impl->group) {
|
||||||
|
ret = mpp_buffer_group_get_external(&impl->group, MPP_BUFFER_TYPE_ION);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err_f("get mpp external buffer group failed ret %d\n", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: Use default misc allocater here as external allocator for demo.
|
||||||
|
* But in practical case the external buffer could be GraphicBuffer or gst dmabuf.
|
||||||
|
* The misc allocator will cause the print at the end like:
|
||||||
|
* ~MppBufferService cleaning misc group
|
||||||
|
*/
|
||||||
|
commit.type = MPP_BUFFER_TYPE_ION;
|
||||||
|
commit.size = size;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
ret = mpp_buffer_get(NULL, &impl->bufs[i], size);
|
||||||
|
if (ret || NULL == impl->bufs[i]) {
|
||||||
|
mpp_err_f("get misc buffer failed ret %d\n", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
commit.index = i;
|
||||||
|
commit.ptr = mpp_buffer_get_ptr(impl->bufs[i]);
|
||||||
|
commit.fd = mpp_buffer_get_fd(impl->bufs[i]);
|
||||||
|
|
||||||
|
ret = mpp_buffer_commit(impl->group, &commit);
|
||||||
|
if (ret) {
|
||||||
|
mpp_err_f("external buffer commit failed ret %d\n", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default : {
|
||||||
|
mpp_err_f("unsupport buffer mode %d\n", mode);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
dec_buf_mgr_deinit(impl);
|
||||||
|
impl = NULL;
|
||||||
|
} else {
|
||||||
|
impl->buf_count = count;
|
||||||
|
impl->buf_size = size;
|
||||||
|
impl->buf_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return impl ? impl->group : NULL;
|
||||||
|
}
|
@@ -24,7 +24,74 @@
|
|||||||
#define MPI_DEC_STREAM_SIZE (SZ_4K)
|
#define MPI_DEC_STREAM_SIZE (SZ_4K)
|
||||||
#define MPI_DEC_LOOP_COUNT 4
|
#define MPI_DEC_LOOP_COUNT 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: We can choose decoder's buffer mode here.
|
||||||
|
* There are three mode that decoder can support:
|
||||||
|
*
|
||||||
|
* Mode 1: Pure internal mode
|
||||||
|
* In the mode user will NOT call MPP_DEC_SET_EXT_BUF_GROUP
|
||||||
|
* control to decoder. Only call MPP_DEC_SET_INFO_CHANGE_READY
|
||||||
|
* to let decoder go on. Then decoder will use create buffer
|
||||||
|
* internally and user need to release each frame they get.
|
||||||
|
*
|
||||||
|
* Advantage:
|
||||||
|
* Easy to use and get a demo quickly
|
||||||
|
* Disadvantage:
|
||||||
|
* 1. The buffer from decoder may not be return before
|
||||||
|
* decoder is close. So memroy leak or crash may happen.
|
||||||
|
* 2. The decoder memory usage can not be control. Decoder
|
||||||
|
* is on a free-to-run status and consume all memory it can
|
||||||
|
* get.
|
||||||
|
* 3. Difficult to implement zero-copy display path.
|
||||||
|
*
|
||||||
|
* Mode 2: Half internal mode
|
||||||
|
* This is the mode current test code using. User need to
|
||||||
|
* create MppBufferGroup according to the returned info
|
||||||
|
* change MppFrame. User can use mpp_buffer_group_limit_config
|
||||||
|
* function to limit decoder memory usage.
|
||||||
|
*
|
||||||
|
* Advantage:
|
||||||
|
* 1. Easy to use
|
||||||
|
* 2. User can release MppBufferGroup after decoder is closed.
|
||||||
|
* So memory can stay longer safely.
|
||||||
|
* 3. Can limit the memory usage by mpp_buffer_group_limit_config
|
||||||
|
* Disadvantage:
|
||||||
|
* 1. The buffer limitation is still not accurate. Memory usage
|
||||||
|
* is 100% fixed.
|
||||||
|
* 2. Also difficult to implement zero-copy display path.
|
||||||
|
*
|
||||||
|
* Mode 3: Pure external mode
|
||||||
|
* In this mode use need to create empty MppBufferGroup and
|
||||||
|
* import memory from external allocator by file handle.
|
||||||
|
* On Android surfaceflinger will create buffer. Then
|
||||||
|
* mediaserver get the file handle from surfaceflinger and
|
||||||
|
* commit to decoder's MppBufferGroup.
|
||||||
|
*
|
||||||
|
* Advantage:
|
||||||
|
* 1. Most efficient way for zero-copy display
|
||||||
|
* Disadvantage:
|
||||||
|
* 1. Difficult to learn and use.
|
||||||
|
* 2. Player work flow may limit this usage.
|
||||||
|
* 3. May need a external parser to get the correct buffer
|
||||||
|
* size for the external allocator.
|
||||||
|
*
|
||||||
|
* The required buffer size caculation:
|
||||||
|
* hor_stride * ver_stride * 3 / 2 for pixel data
|
||||||
|
* hor_stride * ver_stride / 2 for extra info
|
||||||
|
* Total hor_stride * ver_stride * 2 will be enough.
|
||||||
|
*
|
||||||
|
* For H.264/H.265 20+ buffers will be enough.
|
||||||
|
* For other codec 10 buffers will be enough.
|
||||||
|
*/
|
||||||
|
typedef enum MppDecBufMode_e {
|
||||||
|
MPP_DEC_BUF_HALF_INT,
|
||||||
|
MPP_DEC_BUF_INTERNAL,
|
||||||
|
MPP_DEC_BUF_EXTERNAL,
|
||||||
|
MPP_DEC_BUF_MODE_BUTT,
|
||||||
|
} MppDecBufMode;
|
||||||
|
|
||||||
typedef void* FileReader;
|
typedef void* FileReader;
|
||||||
|
typedef void* DecBufMgr;
|
||||||
|
|
||||||
typedef struct FileBufSlot_t {
|
typedef struct FileBufSlot_t {
|
||||||
RK_S32 index;
|
RK_S32 index;
|
||||||
@@ -51,6 +118,8 @@ typedef struct MpiDecTestCmd_t {
|
|||||||
RK_S32 timeout;
|
RK_S32 timeout;
|
||||||
RK_S32 frame_num;
|
RK_S32 frame_num;
|
||||||
size_t pkt_size;
|
size_t pkt_size;
|
||||||
|
MppDecBufMode buf_mode;
|
||||||
|
|
||||||
/* use for mpi_dec_multi_test */
|
/* use for mpi_dec_multi_test */
|
||||||
RK_S32 nthreads;
|
RK_S32 nthreads;
|
||||||
// report information
|
// report information
|
||||||
@@ -66,8 +135,6 @@ typedef struct MpiDecTestCmd_t {
|
|||||||
char *file_slt;
|
char *file_slt;
|
||||||
} MpiDecTestCmd;
|
} MpiDecTestCmd;
|
||||||
|
|
||||||
extern OptionInfo mpi_dec_cmd[];
|
|
||||||
|
|
||||||
RK_S32 mpi_dec_test_cmd_init(MpiDecTestCmd* cmd, int argc, char **argv);
|
RK_S32 mpi_dec_test_cmd_init(MpiDecTestCmd* cmd, int argc, char **argv);
|
||||||
RK_S32 mpi_dec_test_cmd_deinit(MpiDecTestCmd* cmd);
|
RK_S32 mpi_dec_test_cmd_deinit(MpiDecTestCmd* cmd);
|
||||||
void mpi_dec_test_cmd_options(MpiDecTestCmd* cmd);
|
void mpi_dec_test_cmd_options(MpiDecTestCmd* cmd);
|
||||||
@@ -84,6 +151,10 @@ MPP_RET reader_read(FileReader reader, FileBufSlot **buf);
|
|||||||
MPP_RET reader_index_read(FileReader reader, RK_S32 index, FileBufSlot **buf);
|
MPP_RET reader_index_read(FileReader reader, RK_S32 index, FileBufSlot **buf);
|
||||||
void reader_rewind(FileReader reader);
|
void reader_rewind(FileReader reader);
|
||||||
|
|
||||||
|
MPP_RET dec_buf_mgr_init(DecBufMgr *mgr);
|
||||||
|
void dec_buf_mgr_deinit(DecBufMgr mgr);
|
||||||
|
MppBufferGroup dec_buf_mgr_setup(DecBufMgr mgr, RK_U32 size, RK_U32 count, MppDecBufMode mode);
|
||||||
|
|
||||||
void show_dec_fps(RK_S64 total_time, RK_S64 total_count, RK_S64 last_time, RK_S64 last_count);
|
void show_dec_fps(RK_S64 total_time, RK_S64 total_count, RK_S64 last_time, RK_S64 last_count);
|
||||||
|
|
||||||
#endif
|
#endif
|
Reference in New Issue
Block a user