[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; RK_U32 low_delay_part_mode;
/* base task information */ /* base task information */
HalTaskGroup tasks;
HalTaskHnd hnd;
EncAsyncTaskInfo *async;
RK_U32 task_idx; RK_U32 task_idx;
RK_S64 task_pts; RK_S64 task_pts;
MppBuffer frm_buf; MppBuffer frm_buf;

View File

@@ -56,62 +56,6 @@ typedef union EncAsyncWait_u {
}; };
} EncAsyncWait; } 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] = { static RK_U8 uuid_version[16] = {
0x3d, 0x07, 0x6d, 0x45, 0x73, 0x0f, 0x41, 0xa8, 0x3d, 0x07, 0x6d, 0x45, 0x73, 0x0f, 0x41, 0xa8,
0xb1, 0xc4, 0x25, 0xd7, 0x97, 0x6b, 0xf1, 0xac, 0xb1, 0xc4, 0x25, 0xd7, 0x97, 0x6b, 0xf1, 0xac,
@@ -2159,18 +2103,18 @@ void *mpp_enc_thread(void *data)
return NULL; return NULL;
} }
static void async_task_reset(EncAsyncTask *task) static void async_task_reset(EncAsyncTaskInfo *task)
{ {
memset(&task->info, 0, sizeof(task->info)); memset(task, 0, sizeof(*task));
task->info.task.rc_task = &task->info.rc; task->task.rc_task = &task->rc;
task->info.task.frm_cfg = &task->info.usr; task->task.frm_cfg = &task->usr;
task->info.usr.force_flag = 0; 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; HalEncTask *hal_task = &async->task;
EncFrmStatus *frm = &async->info.rc.frm; EncFrmStatus *frm = &async->rc.frm;
Mpp *mpp = (Mpp *)enc->mpp; Mpp *mpp = (Mpp *)enc->mpp;
mpp_stopwatch_record(hal_task->stopwatch, "encode task done"); 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"); 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; MppPacket packet = hal_task->packet;
MppFrame frame = hal_task->frame; 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; 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) { if (NULL == hal_task->output) {
/* NOTE: set buffer w * h * 1.5 to avoid buffer overflow */ /* 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; 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; Mpp *mpp = (Mpp *)enc->mpp;
EncRcTask *rc_task = &async->info.rc; EncAsyncTaskInfo *async = enc->async;
EncFrmStatus *frm = &rc_task->frm; EncRcTask *rc_task = NULL;
MppEncHeaderStatus *hdr_status = &enc->hdr_status; MppEncHeaderStatus *hdr_status = &enc->hdr_status;
HalEncTask *hal_task = &async->info.task; HalEncTask *hal_task = NULL;
EncAsyncStatus *status = &async->info.status; EncAsyncStatus *status = NULL;
MppStopwatch stopwatch = NULL; MppStopwatch stopwatch = NULL;
MppPacket packet = hal_task->packet; MppPacket packet = NULL;
MppFrame frame = hal_task->frame; MppFrame frame = NULL;
RK_U32 seq_idx = 0; RK_U32 seq_idx = 0;
MPP_RET ret = MPP_OK; MPP_RET ret = MPP_OK;
if (NULL == async->hnd) { if (NULL == enc->hnd) {
hal_task_get_hnd(async->tasks, TASK_IDLE, &async->hnd); hal_task_get_hnd(enc->tasks, TASK_IDLE, &enc->hnd);
if (async->hnd) { if (enc->hnd) {
status->task_hnd_rdy = 1;
wait->task_hnd = 0; wait->task_hnd = 0;
enc_dbg_detail("get hnd success\n"); 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); async_task_reset(async);
enc->async = async;
} else { } else {
wait->task_hnd = 1; wait->task_hnd = 1;
enc_dbg_detail("get hnd failed\n"); 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 (NULL == frame) {
if (mpp->mFrmIn) { if (mpp->mFrmIn) {
mpp_list *frm_in = 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; hal_task->stopwatch = stopwatch;
enc_dbg_detail("task frame packet ready\n"); enc_dbg_detail("task frame packet ready\n");
async->info.seq_idx = enc->task_idx++; async->seq_idx = enc->task_idx++;
async->info.pts = mpp_frame_get_pts(hal_task->frame); 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); 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 // 9. check frame drop by frame rate conversion
if (!status->rc_check_frm_drop) { 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); ENC_RUN_FUNC2(rc_frm_check_drop, enc->rc_ctx, rc_task, enc->mpp, ret);
status->rc_check_frm_drop = 1; status->rc_check_frm_drop = 1;
enc_dbg_detail("task %d drop %d\n", seq_idx, frm->drop); 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 // 14. setup user_cfg to dpb
if (!status->refs_force_update) { if (!status->refs_force_update) {
MppEncRefFrmUsrCfg *frm_cfg = &async->info.usr; MppEncRefFrmUsrCfg *frm_cfg = &async->usr;
if (frm_cfg->force_flag) { if (frm_cfg->force_flag) {
mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg); mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
@@ -2540,19 +2498,20 @@ TASK_DONE:
return ret; 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; Mpp *mpp = (Mpp*)enc->mpp;
EncImpl impl = enc->impl; EncImpl impl = enc->impl;
MppEncHal hal = enc->enc_hal; MppEncHal hal = enc->enc_hal;
MppEncHeaderStatus *hdr_status = &enc->hdr_status; MppEncHeaderStatus *hdr_status = &enc->hdr_status;
EncAsyncStatus *status = &async->info.status; EncAsyncTaskInfo *async = enc->async;
HalEncTask *hal_task = &async->info.task; EncAsyncStatus *status = &async->status;
HalEncTask *hal_task = &async->task;
EncRcTask *rc_task = hal_task->rc_task; EncRcTask *rc_task = hal_task->rc_task;
EncCpbStatus *cpb = &rc_task->cpb; EncCpbStatus *cpb = &rc_task->cpb;
EncFrmStatus *frm = &rc_task->frm; EncFrmStatus *frm = &rc_task->frm;
MppPacket packet = hal_task->packet; 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_RET ret = MPP_OK;
mpp_assert(hal_task->valid); mpp_assert(hal_task->valid);
@@ -2631,12 +2590,11 @@ static MPP_RET proc_async_task(MppEncImpl *enc, EncAsyncTask *async)
SEND_TASK_INFO: SEND_TASK_INFO:
status->enc_done = 0; status->enc_done = 0;
hal_task_hnd_set_info(async->hnd, &async->info); hal_task_hnd_set_status(enc->hnd, TASK_PROCESSING);
hal_task_hnd_set_status(async->hnd, TASK_PROCESSING);
enc_dbg_detail("task %d on processing ret %d\n", frm->seq_idx, ret); enc_dbg_detail("task %d on processing ret %d\n", frm->seq_idx, ret);
async_task_reset(async); enc->hnd = NULL;
async->hnd = NULL; enc->async = NULL;
TASK_DONE: TASK_DONE:
@@ -2744,26 +2702,13 @@ void *mpp_enc_async_thread(void *data)
Mpp *mpp = (Mpp*)data; Mpp *mpp = (Mpp*)data;
MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
MppThread *thd_enc = enc->thread_enc; MppThread *thd_enc = enc->thread_enc;
HalTaskGroup tasks = NULL;
EncAsyncTask task;
EncAsyncWait wait; EncAsyncWait wait;
HalTaskHnd hnd = NULL;
MPP_RET ret = MPP_OK; MPP_RET ret = MPP_OK;
enc_dbg_func("thread start\n"); enc_dbg_func("thread start\n");
async_task_reset(&task);
task.hnd = NULL;
wait.val = 0; 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) { while (1) {
{ {
AutoMutex autolock(thd_enc->mutex()); AutoMutex autolock(thd_enc->mutex());
@@ -2781,6 +2726,8 @@ void *mpp_enc_async_thread(void *data)
// 1. process user control and reset flag // 1. process user control and reset flag
if (enc->cmd_send != enc->cmd_recv || enc->reset_flag) { if (enc->cmd_send != enc->cmd_recv || enc->reset_flag) {
mpp_list *frm_in = mpp->mFrmIn; mpp_list *frm_in = mpp->mFrmIn;
HalTaskHnd hnd = NULL;
EncAsyncTaskInfo *info = NULL;
/* when process cmd or reset hold frame input */ /* when process cmd or reset hold frame input */
frm_in->lock(); 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); enc_dbg_detail("ctrl proc %d cmd %08x\n", enc->cmd_recv, enc->cmd);
// wait all tasks done // wait all tasks done
while (MPP_OK == hal_task_get_hnd(tasks, TASK_PROCESSING, &hnd)) { while (MPP_OK == hal_task_get_hnd(enc->tasks, TASK_PROCESSING, &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); enc_async_wait_task(enc, info);
enc_async_wait_task(enc, &info);
hal_task_hnd_set_status(hnd, TASK_IDLE); hal_task_hnd_set_status(hnd, TASK_IDLE);
wait.task_hnd = 0; wait.task_hnd = 0;
} }
@@ -2845,22 +2791,19 @@ void *mpp_enc_async_thread(void *data)
} }
// 2. try get a task to encode // 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); enc_dbg_detail("try_get_async_task ret %d\n", ret);
if (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) { 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); enc_async_wait_task(enc, info);
/* NOTE: update pointer in rc_task */
info.task.rc_task = &info.rc;
info.task.frm_cfg = &info.usr;
enc_async_wait_task(enc, &info);
hal_task_hnd_set_status(hnd, TASK_IDLE); hal_task_hnd_set_status(hnd, TASK_IDLE);
wait.task_hnd = 0; wait.task_hnd = 0;
} }
@@ -2868,17 +2811,10 @@ void *mpp_enc_async_thread(void *data)
continue; continue;
} }
mpp_assert(task.info.task.valid); mpp_assert(enc->async);
mpp_assert(enc->async->task.valid);
proc_async_task(enc, &task); proc_async_task(enc);
}
DONE:
enc_dbg_func("loop done\n");
if (tasks) {
ret = hal_task_group_deinit(tasks);
tasks = NULL;
} }
enc_dbg_func("thread finish\n"); 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->enc_hal = enc_hal;
p->dev = enc_hal_cfg.dev; p->dev = enc_hal_cfg.dev;
p->mpp = cfg->mpp; p->mpp = cfg->mpp;
p->tasks = enc_hal_cfg.tasks;
p->sei_mode = MPP_ENC_SEI_MODE_ONE_SEQ; p->sei_mode = MPP_ENC_SEI_MODE_ONE_SEQ;
p->version_info = get_mpp_version(); p->version_info = get_mpp_version();
p->version_length = strlen(p->version_info); p->version_length = strlen(p->version_info);

View File

@@ -101,4 +101,53 @@ typedef struct HalEncTask_t {
HalEncTaskFlag flags; HalEncTaskFlag flags;
} HalEncTask; } 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__ */ #endif /* __HAL_ENC_TASK__ */

View File

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

View File

@@ -49,6 +49,8 @@ typedef struct MppEncHalImpl_t {
void *ctx; void *ctx;
const MppEncHalApi *api; const MppEncHalApi *api;
HalTaskGroup tasks;
} MppEncHalImpl; } MppEncHalImpl;
MPP_RET mpp_enc_hal_init(MppEncHal *ctx, MppEncHalCfg *cfg) 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; 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; *ctx = p;
return MPP_OK; return MPP_OK;
} }
@@ -100,6 +110,8 @@ MPP_RET mpp_enc_hal_deinit(MppEncHal ctx)
MppEncHalImpl *p = (MppEncHalImpl*)ctx; MppEncHalImpl *p = (MppEncHalImpl*)ctx;
p->api->deinit(p->ctx); p->api->deinit(p->ctx);
mpp_free(p->ctx); mpp_free(p->ctx);
if (p->tasks)
hal_task_group_deinit(p->tasks);
mpp_free(p); mpp_free(p);
return MPP_OK; return MPP_OK;
} }