From f50df9b27290d63ab972743be8a8fc0936bf94a9 Mon Sep 17 00:00:00 2001 From: Herman Chen Date: Thu, 21 Apr 2022 08:32:30 +0800 Subject: [PATCH] [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 --- mpp/codec/inc/mpp_enc_impl.h | 3 + mpp/codec/mpp_enc_impl.cpp | 198 ++++++++++++----------------------- mpp/codec/mpp_enc_v2.cpp | 1 + mpp/hal/inc/hal_enc_task.h | 49 +++++++++ mpp/hal/inc/mpp_enc_hal.h | 1 + mpp/hal/mpp_enc_hal.cpp | 12 +++ 6 files changed, 133 insertions(+), 131 deletions(-) diff --git a/mpp/codec/inc/mpp_enc_impl.h b/mpp/codec/inc/mpp_enc_impl.h index 345c9a68..a84966eb 100644 --- a/mpp/codec/inc/mpp_enc_impl.h +++ b/mpp/codec/inc/mpp_enc_impl.h @@ -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; diff --git a/mpp/codec/mpp_enc_impl.cpp b/mpp/codec/mpp_enc_impl.cpp index 2efa83e6..df164f5b 100644 --- a/mpp/codec/mpp_enc_impl.cpp +++ b/mpp/codec/mpp_enc_impl.cpp @@ -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"); diff --git a/mpp/codec/mpp_enc_v2.cpp b/mpp/codec/mpp_enc_v2.cpp index 00a988e8..90fdfe95 100644 --- a/mpp/codec/mpp_enc_v2.cpp +++ b/mpp/codec/mpp_enc_v2.cpp @@ -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); diff --git a/mpp/hal/inc/hal_enc_task.h b/mpp/hal/inc/hal_enc_task.h index 8f4f2c57..ce83586a 100644 --- a/mpp/hal/inc/hal_enc_task.h +++ b/mpp/hal/inc/hal_enc_task.h @@ -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__ */ diff --git a/mpp/hal/inc/mpp_enc_hal.h b/mpp/hal/inc/mpp_enc_hal.h index 89691f07..16ceabb6 100644 --- a/mpp/hal/inc/mpp_enc_hal.h +++ b/mpp/hal/inc/mpp_enc_hal.h @@ -31,6 +31,7 @@ typedef struct MppEncHalCfg_t { MppClientType type; MppDev dev; RK_S32 cap_recn_out; + HalTaskGroup tasks; } MppEncHalCfg; typedef struct MppEncHalApi_t { diff --git a/mpp/hal/mpp_enc_hal.cpp b/mpp/hal/mpp_enc_hal.cpp index a8f51f76..c4104ce2 100644 --- a/mpp/hal/mpp_enc_hal.cpp +++ b/mpp/hal/mpp_enc_hal.cpp @@ -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; }