[mpp_enc]: Optimize encoder flow

1. Create hal_task_group in mpp_enc_hal.
2. Reduce EncAsyncTaskInfo copy in async flow.

Change-Id: If81ffc72122f87eb6d2f83bb5ecd7de5400bc140
Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
This commit is contained in:
Herman Chen
2022-04-21 08:32:30 +08:00
parent a99d8e9921
commit f50df9b272
6 changed files with 133 additions and 131 deletions

View File

@@ -80,6 +80,9 @@ typedef struct MppEncImpl_t {
RK_U32 low_delay_part_mode;
/* base task information */
HalTaskGroup tasks;
HalTaskHnd hnd;
EncAsyncTaskInfo *async;
RK_U32 task_idx;
RK_S64 task_pts;
MppBuffer frm_buf;

View File

@@ -56,62 +56,6 @@ typedef union EncAsyncWait_u {
};
} EncAsyncWait;
/* encoder internal work flow */
typedef union EncAsyncStatus_u {
RK_U32 val;
struct {
RK_U32 task_hnd_rdy : 1;
RK_U32 task_in_rdy : 1;
RK_U32 task_out_rdy : 1;
RK_U32 frm_pkt_rdy : 1;
RK_U32 hal_task_reset_rdy : 1; // reset hal task to start
RK_U32 rc_check_frm_drop : 1; // rc stage
RK_U32 pkt_buf_rdy : 1; // prepare pkt buf
RK_U32 enc_start : 1; // enc stage
RK_U32 refs_force_update : 1; // enc stage
RK_U32 low_delay_again : 1; // enc stage low delay output again
RK_U32 enc_backup : 1; // enc stage
RK_U32 enc_restore : 1; // reenc flow start point
RK_U32 enc_proc_dpb : 1; // enc stage
RK_U32 rc_frm_start : 1; // rc stage
RK_U32 check_type_reenc : 1; // flow checkpoint if reenc -> enc_restore
RK_U32 enc_proc_hal : 1; // enc stage
RK_U32 hal_get_task : 1; // hal stage
RK_U32 rc_hal_start : 1; // rc stage
RK_U32 hal_gen_reg : 1; // hal stage
RK_U32 hal_start : 1; // hal stage
RK_U32 hal_wait : 1; // hal stage NOTE: special in low delay mode
RK_U32 rc_hal_end : 1; // rc stage
RK_U32 hal_ret_task : 1; // hal stage
RK_U32 enc_update_hal : 1; // enc stage
RK_U32 rc_frm_end : 1; // rc stage
RK_U32 check_rc_reenc : 1; // flow checkpoint if reenc -> enc_restore
RK_U32 enc_done : 1; // done stage
RK_U32 slice_out_done : 1;
};
} EncAsyncStatus;
typedef struct EncAsyncTaskInfo_t {
RK_S32 seq_idx;
EncAsyncStatus status;
RK_S64 pts;
HalEncTask task;
EncRcTask rc;
MppEncRefFrmUsrCfg usr;
} EncAsyncTaskInfo;
typedef struct EncAsyncTask_t {
HalTaskGroup tasks;
HalTaskHnd hnd;
EncAsyncTaskInfo info;
} EncAsyncTask;
static RK_U8 uuid_version[16] = {
0x3d, 0x07, 0x6d, 0x45, 0x73, 0x0f, 0x41, 0xa8,
0xb1, 0xc4, 0x25, 0xd7, 0x97, 0x6b, 0xf1, 0xac,
@@ -2159,18 +2103,18 @@ void *mpp_enc_thread(void *data)
return NULL;
}
static void async_task_reset(EncAsyncTask *task)
static void async_task_reset(EncAsyncTaskInfo *task)
{
memset(&task->info, 0, sizeof(task->info));
task->info.task.rc_task = &task->info.rc;
task->info.task.frm_cfg = &task->info.usr;
task->info.usr.force_flag = 0;
memset(task, 0, sizeof(*task));
task->task.rc_task = &task->rc;
task->task.frm_cfg = &task->usr;
task->usr.force_flag = 0;
}
static void async_task_terminate(MppEncImpl *enc, EncAsyncTask *async)
static void async_task_terminate(MppEncImpl *enc, EncAsyncTaskInfo *async)
{
HalEncTask *hal_task = &async->info.task;
EncFrmStatus *frm = &async->info.rc.frm;
HalEncTask *hal_task = &async->task;
EncFrmStatus *frm = &async->rc.frm;
Mpp *mpp = (Mpp *)enc->mpp;
mpp_stopwatch_record(hal_task->stopwatch, "encode task done");
@@ -2271,9 +2215,9 @@ static void async_task_skip(MppEncImpl *enc)
enc_dbg_detail("packet skip ready\n");
}
static MPP_RET check_async_frm_pkt(EncAsyncTask *async)
static MPP_RET check_async_frm_pkt(EncAsyncTaskInfo *async)
{
HalEncTask *hal_task = &async->info.task;
HalEncTask *hal_task = &async->task;
MppPacket packet = hal_task->packet;
MppFrame frame = hal_task->frame;
@@ -2304,9 +2248,9 @@ static MPP_RET check_async_frm_pkt(EncAsyncTask *async)
return (NULL == frame || NULL == hal_task->input) ? MPP_NOK : MPP_OK;
}
static MPP_RET check_async_pkt_buf(MppEncImpl *enc, EncAsyncTask *async)
static MPP_RET check_async_pkt_buf(MppEncImpl *enc, EncAsyncTaskInfo *async)
{
HalEncTask *hal_task = &async->info.task;
HalEncTask *hal_task = &async->task;
if (NULL == hal_task->output) {
/* NOTE: set buffer w * h * 1.5 to avoid buffer overflow */
@@ -2341,27 +2285,30 @@ static MPP_RET check_async_pkt_buf(MppEncImpl *enc, EncAsyncTask *async)
return MPP_OK;
}
static MPP_RET try_get_async_task(MppEncImpl *enc, EncAsyncTask *async, EncAsyncWait *wait)
static MPP_RET try_get_async_task(MppEncImpl *enc, EncAsyncWait *wait)
{
Mpp *mpp = (Mpp *)enc->mpp;
EncRcTask *rc_task = &async->info.rc;
EncFrmStatus *frm = &rc_task->frm;
EncAsyncTaskInfo *async = enc->async;
EncRcTask *rc_task = NULL;
MppEncHeaderStatus *hdr_status = &enc->hdr_status;
HalEncTask *hal_task = &async->info.task;
EncAsyncStatus *status = &async->info.status;
HalEncTask *hal_task = NULL;
EncAsyncStatus *status = NULL;
MppStopwatch stopwatch = NULL;
MppPacket packet = hal_task->packet;
MppFrame frame = hal_task->frame;
MppPacket packet = NULL;
MppFrame frame = NULL;
RK_U32 seq_idx = 0;
MPP_RET ret = MPP_OK;
if (NULL == async->hnd) {
hal_task_get_hnd(async->tasks, TASK_IDLE, &async->hnd);
if (async->hnd) {
status->task_hnd_rdy = 1;
if (NULL == enc->hnd) {
hal_task_get_hnd(enc->tasks, TASK_IDLE, &enc->hnd);
if (enc->hnd) {
wait->task_hnd = 0;
enc_dbg_detail("get hnd success\n");
mpp_assert(enc->async == NULL);
async = (EncAsyncTaskInfo *)hal_task_hnd_get_data(enc->hnd);
async_task_reset(async);
enc->async = async;
} else {
wait->task_hnd = 1;
enc_dbg_detail("get hnd failed\n");
@@ -2369,6 +2316,15 @@ static MPP_RET try_get_async_task(MppEncImpl *enc, EncAsyncTask *async, EncAsync
}
}
mpp_assert(enc->hnd);
mpp_assert(enc->async);
hal_task = &async->task;
rc_task = &async->rc;
status = &async->status;
packet = hal_task->packet;
frame = hal_task->frame;
if (NULL == frame) {
if (mpp->mFrmIn) {
mpp_list *frm_in = mpp->mFrmIn;
@@ -2436,17 +2392,19 @@ static MPP_RET try_get_async_task(MppEncImpl *enc, EncAsyncTask *async, EncAsync
hal_task->stopwatch = stopwatch;
enc_dbg_detail("task frame packet ready\n");
async->info.seq_idx = enc->task_idx++;
async->info.pts = mpp_frame_get_pts(hal_task->frame);
async->seq_idx = enc->task_idx++;
async->pts = mpp_frame_get_pts(hal_task->frame);
rc_task->frame = async->info.task.frame;
rc_task->frame = async->task.frame;
enc_dbg_detail("task seq idx %d start\n", seq_idx);
}
seq_idx = async->info.seq_idx;
seq_idx = async->seq_idx;
// 9. check frame drop by frame rate conversion
if (!status->rc_check_frm_drop) {
EncFrmStatus *frm = &rc_task->frm;
ENC_RUN_FUNC2(rc_frm_check_drop, enc->rc_ctx, rc_task, enc->mpp, ret);
status->rc_check_frm_drop = 1;
enc_dbg_detail("task %d drop %d\n", seq_idx, frm->drop);
@@ -2513,7 +2471,7 @@ static MPP_RET try_get_async_task(MppEncImpl *enc, EncAsyncTask *async, EncAsync
// 14. setup user_cfg to dpb
if (!status->refs_force_update) {
MppEncRefFrmUsrCfg *frm_cfg = &async->info.usr;
MppEncRefFrmUsrCfg *frm_cfg = &async->usr;
if (frm_cfg->force_flag) {
mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
@@ -2540,19 +2498,20 @@ TASK_DONE:
return ret;
}
static MPP_RET proc_async_task(MppEncImpl *enc, EncAsyncTask *async)
static MPP_RET proc_async_task(MppEncImpl *enc)
{
Mpp *mpp = (Mpp*)enc->mpp;
EncImpl impl = enc->impl;
MppEncHal hal = enc->enc_hal;
MppEncHeaderStatus *hdr_status = &enc->hdr_status;
EncAsyncStatus *status = &async->info.status;
HalEncTask *hal_task = &async->info.task;
EncAsyncTaskInfo *async = enc->async;
EncAsyncStatus *status = &async->status;
HalEncTask *hal_task = &async->task;
EncRcTask *rc_task = hal_task->rc_task;
EncCpbStatus *cpb = &rc_task->cpb;
EncFrmStatus *frm = &rc_task->frm;
MppPacket packet = hal_task->packet;
RK_U32 seq_idx = async->info.seq_idx;
RK_U32 seq_idx = async->seq_idx;
MPP_RET ret = MPP_OK;
mpp_assert(hal_task->valid);
@@ -2631,12 +2590,11 @@ static MPP_RET proc_async_task(MppEncImpl *enc, EncAsyncTask *async)
SEND_TASK_INFO:
status->enc_done = 0;
hal_task_hnd_set_info(async->hnd, &async->info);
hal_task_hnd_set_status(async->hnd, TASK_PROCESSING);
hal_task_hnd_set_status(enc->hnd, TASK_PROCESSING);
enc_dbg_detail("task %d on processing ret %d\n", frm->seq_idx, ret);
async_task_reset(async);
async->hnd = NULL;
enc->hnd = NULL;
enc->async = NULL;
TASK_DONE:
@@ -2744,26 +2702,13 @@ void *mpp_enc_async_thread(void *data)
Mpp *mpp = (Mpp*)data;
MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
MppThread *thd_enc = enc->thread_enc;
HalTaskGroup tasks = NULL;
EncAsyncTask task;
EncAsyncWait wait;
HalTaskHnd hnd = NULL;
MPP_RET ret = MPP_OK;
enc_dbg_func("thread start\n");
async_task_reset(&task);
task.hnd = NULL;
wait.val = 0;
/* init two task for */
ret = hal_task_group_init(&tasks, 2, sizeof(EncAsyncTaskInfo));
if (ret) {
mpp_err_f("hal_task_group_init failed ret %d\n", ret);
goto DONE;;
}
task.tasks = tasks;
while (1) {
{
AutoMutex autolock(thd_enc->mutex());
@@ -2781,6 +2726,8 @@ void *mpp_enc_async_thread(void *data)
// 1. process user control and reset flag
if (enc->cmd_send != enc->cmd_recv || enc->reset_flag) {
mpp_list *frm_in = mpp->mFrmIn;
HalTaskHnd hnd = NULL;
EncAsyncTaskInfo *info = NULL;
/* when process cmd or reset hold frame input */
frm_in->lock();
@@ -2788,13 +2735,12 @@ void *mpp_enc_async_thread(void *data)
enc_dbg_detail("ctrl proc %d cmd %08x\n", enc->cmd_recv, enc->cmd);
// wait all tasks done
while (MPP_OK == hal_task_get_hnd(tasks, TASK_PROCESSING, &hnd)) {
EncAsyncTaskInfo info;
while (MPP_OK == hal_task_get_hnd(enc->tasks, TASK_PROCESSING, &hnd)) {
info = (EncAsyncTaskInfo *)hal_task_hnd_get_data(hnd);
hal_task_hnd_get_info(hnd, &info);
mpp_assert(!info->status.enc_done);
mpp_assert(!info.status.enc_done);
enc_async_wait_task(enc, &info);
enc_async_wait_task(enc, info);
hal_task_hnd_set_status(hnd, TASK_IDLE);
wait.task_hnd = 0;
}
@@ -2845,22 +2791,19 @@ void *mpp_enc_async_thread(void *data)
}
// 2. try get a task to encode
ret = try_get_async_task(enc, &task, &wait);
ret = try_get_async_task(enc, &wait);
enc_dbg_detail("try_get_async_task ret %d\n", ret);
if (ret) {
hal_task_get_hnd(tasks, TASK_PROCESSING, &hnd);
HalTaskHnd hnd = NULL;
EncAsyncTaskInfo *info = NULL;
hal_task_get_hnd(enc->tasks, TASK_PROCESSING, &hnd);
if (hnd) {
EncAsyncTaskInfo info;
info = (EncAsyncTaskInfo *)hal_task_hnd_get_data(hnd);
hal_task_hnd_get_info(hnd, &info);
mpp_assert(!info->status.enc_done);
mpp_assert(!info.status.enc_done);
/* NOTE: update pointer in rc_task */
info.task.rc_task = &info.rc;
info.task.frm_cfg = &info.usr;
enc_async_wait_task(enc, &info);
enc_async_wait_task(enc, info);
hal_task_hnd_set_status(hnd, TASK_IDLE);
wait.task_hnd = 0;
}
@@ -2868,17 +2811,10 @@ void *mpp_enc_async_thread(void *data)
continue;
}
mpp_assert(task.info.task.valid);
mpp_assert(enc->async);
mpp_assert(enc->async->task.valid);
proc_async_task(enc, &task);
}
DONE:
enc_dbg_func("loop done\n");
if (tasks) {
ret = hal_task_group_deinit(tasks);
tasks = NULL;
proc_async_task(enc);
}
enc_dbg_func("thread finish\n");

View File

@@ -101,6 +101,7 @@ MPP_RET mpp_enc_init_v2(MppEnc *enc, MppEncInitCfg *cfg)
p->enc_hal = enc_hal;
p->dev = enc_hal_cfg.dev;
p->mpp = cfg->mpp;
p->tasks = enc_hal_cfg.tasks;
p->sei_mode = MPP_ENC_SEI_MODE_ONE_SEQ;
p->version_info = get_mpp_version();
p->version_length = strlen(p->version_info);

View File

@@ -101,4 +101,53 @@ typedef struct HalEncTask_t {
HalEncTaskFlag flags;
} HalEncTask;
/* encoder internal work flow */
typedef union EncAsyncStatus_u {
RK_U32 val;
struct {
RK_U32 task_hnd_rdy : 1;
RK_U32 task_in_rdy : 1;
RK_U32 task_out_rdy : 1;
RK_U32 frm_pkt_rdy : 1;
RK_U32 hal_task_reset_rdy : 1; // reset hal task to start
RK_U32 rc_check_frm_drop : 1; // rc stage
RK_U32 pkt_buf_rdy : 1; // prepare pkt buf
RK_U32 enc_start : 1; // enc stage
RK_U32 refs_force_update : 1; // enc stage
RK_U32 low_delay_again : 1; // enc stage low delay output again
RK_U32 enc_backup : 1; // enc stage
RK_U32 enc_restore : 1; // reenc flow start point
RK_U32 enc_proc_dpb : 1; // enc stage
RK_U32 rc_frm_start : 1; // rc stage
RK_U32 check_type_reenc : 1; // flow checkpoint if reenc -> enc_restore
RK_U32 enc_proc_hal : 1; // enc stage
RK_U32 hal_get_task : 1; // hal stage
RK_U32 rc_hal_start : 1; // rc stage
RK_U32 hal_gen_reg : 1; // hal stage
RK_U32 hal_start : 1; // hal stage
RK_U32 hal_wait : 1; // hal stage NOTE: special in low delay mode
RK_U32 rc_hal_end : 1; // rc stage
RK_U32 hal_ret_task : 1; // hal stage
RK_U32 enc_update_hal : 1; // enc stage
RK_U32 rc_frm_end : 1; // rc stage
RK_U32 check_rc_reenc : 1; // flow checkpoint if reenc -> enc_restore
RK_U32 enc_done : 1; // done stage
RK_U32 slice_out_done : 1;
};
} EncAsyncStatus;
typedef struct EncAsyncTaskInfo_t {
RK_S32 seq_idx;
EncAsyncStatus status;
RK_S64 pts;
HalEncTask task;
EncRcTask rc;
MppEncRefFrmUsrCfg usr;
} EncAsyncTaskInfo;
#endif /* __HAL_ENC_TASK__ */

View File

@@ -31,6 +31,7 @@ typedef struct MppEncHalCfg_t {
MppClientType type;
MppDev dev;
RK_S32 cap_recn_out;
HalTaskGroup tasks;
} MppEncHalCfg;
typedef struct MppEncHalApi_t {

View File

@@ -49,6 +49,8 @@ typedef struct MppEncHalImpl_t {
void *ctx;
const MppEncHalApi *api;
HalTaskGroup tasks;
} MppEncHalImpl;
MPP_RET mpp_enc_hal_init(MppEncHal *ctx, MppEncHalCfg *cfg)
@@ -78,6 +80,14 @@ MPP_RET mpp_enc_hal_init(MppEncHal *ctx, MppEncHalCfg *cfg)
break;
}
ret = hal_task_group_init(&p->tasks, cfg->task_cnt,
sizeof(EncAsyncTaskInfo));
if (ret) {
mpp_err_f("hal_task_group_init failed ret %d\n", ret);
break;
}
cfg->tasks = p->tasks;
*ctx = p;
return MPP_OK;
}
@@ -100,6 +110,8 @@ MPP_RET mpp_enc_hal_deinit(MppEncHal ctx)
MppEncHalImpl *p = (MppEncHalImpl*)ctx;
p->api->deinit(p->ctx);
mpp_free(p->ctx);
if (p->tasks)
hal_task_group_deinit(p->tasks);
mpp_free(p);
return MPP_OK;
}