From 069826890fa86ad08eea7945f2333c4a4aa4574e Mon Sep 17 00:00:00 2001 From: Herman Chen Date: Fri, 20 Dec 2019 17:17:25 +0800 Subject: [PATCH] [mpp_enc_v2]: Optimize encoder main flow 1. Add skip flow for frame rate conversion frame drop. 2. Add reencode path for reencoding. Signed-off-by: Herman Chen Change-Id: Ibca23e03d2e82f280bb7db7cf522fb1648f840bf --- mpp/codec/enc/h264/h264e_api_v2.c | 9 +- mpp/codec/mpp_enc_v2.cpp | 203 ++++++++++++++---------------- mpp/hal/inc/hal_task.h | 2 +- 3 files changed, 102 insertions(+), 112 deletions(-) diff --git a/mpp/codec/enc/h264/h264e_api_v2.c b/mpp/codec/enc/h264/h264e_api_v2.c index 6ad344e0..dc3a76e4 100644 --- a/mpp/codec/enc/h264/h264e_api_v2.c +++ b/mpp/codec/enc/h264/h264e_api_v2.c @@ -523,19 +523,18 @@ static MPP_RET h264e_start(void *ctx, HalEncTask *task) * Determine current frame which should be encoded or not according to * input and output frame rate. */ - RK_S32 drop = rc_frm_check_drop(p->rc_ctx); - if (drop) - mpp_log_f("drop one frame\n"); + task->valid = !rc_frm_check_drop(p->rc_ctx); + if (!task->valid) + mpp_log_f("drop one frame by fps\n"); /* * Step 3: Backup dpb for reencode */ h264e_dpb_copy(&p->dpb_bak, &p->dpb); - (void)task; h264e_dbg_func("leave\n"); - return (drop) ? (MPP_NOK) : (MPP_OK); + return MPP_OK; } static MPP_RET h264e_proc_dpb(void *ctx, HalEncTask *task) diff --git a/mpp/codec/mpp_enc_v2.cpp b/mpp/codec/mpp_enc_v2.cpp index c87b9b68..2c44c42e 100644 --- a/mpp/codec/mpp_enc_v2.cpp +++ b/mpp/codec/mpp_enc_v2.cpp @@ -185,11 +185,18 @@ static MPP_RET check_enc_task_wait(MppEncImpl *enc, EncTask *task) return ret; } +#define RUN_ENC_IMPL_FUNC(func, hal, task, mpp, ret) \ + ret = func(hal, task); \ + if (ret) { \ + mpp_err("mpp %p ##func failed return %d", mpp, ret); \ + goto TASK_ERR; \ + } + #define RUN_ENC_HAL_FUNC(func, hal, task, mpp, ret) \ ret = func(hal, task); \ if (ret) { \ mpp_err("mpp %p ##func failed return %d", mpp, ret); \ - goto TASK_END; \ + goto TASK_ERR; \ } void *mpp_enc_thread(void *data) @@ -209,7 +216,7 @@ void *mpp_enc_thread(void *data) MPP_RET ret = MPP_OK; MppFrame frame = NULL; MppPacket packet = NULL; - MppBuffer mv_info = NULL; + MppBuffer frm_buf = NULL; memset(&task, 0, sizeof(task)); @@ -303,17 +310,27 @@ void *mpp_enc_thread(void *data) } enc_dbg_detail("task out ready\n"); + // get tasks from both input and output ret = mpp_port_dequeue(input, &task_in); mpp_assert(task_in); + ret = mpp_port_dequeue(output, &task_out); + mpp_assert(task_out); + + /* + * frame will be return to input. + * packet will be sent to output. + */ mpp_task_meta_get_frame (task_in, KEY_INPUT_FRAME, &frame); mpp_task_meta_get_packet(task_in, KEY_OUTPUT_PACKET, &packet); - mpp_task_meta_get_buffer(task_in, KEY_MOTION_INFO, &mv_info); - if (NULL == frame) { - mpp_port_enqueue(input, task_in); - continue; - } + /* If there is no input frame just return empty packet task */ + if (NULL == frame) + goto TASK_RETURN; + + frm_buf = mpp_frame_get_buffer(frame); + if (NULL == frm_buf) + goto TASK_RETURN; reset_hal_enc_task(hal_task); @@ -322,122 +339,96 @@ void *mpp_enc_thread(void *data) enc->hdr_need_updated = 0; } - if (mpp_frame_get_buffer(frame)) { - /* - * if there is available buffer in the input frame do encoding - */ - if (NULL == packet) { - RK_U32 width = enc->cfg.prep.width; - RK_U32 height = enc->cfg.prep.height; - RK_U32 size = width * height; - MppBuffer buffer = NULL; + /* + * if there is available buffer in the input frame do encoding + */ + if (NULL == packet) { + RK_U32 width = enc->cfg.prep.width; + RK_U32 height = enc->cfg.prep.height; + RK_U32 size = width * height; + MppBuffer buffer = NULL; - mpp_assert(size); - mpp_buffer_get(mpp->mPacketGroup, &buffer, size); - mpp_packet_init_with_buffer(&packet, buffer); - mpp_buffer_put(buffer); - } - mpp_assert(packet); + mpp_assert(size); + mpp_buffer_get(mpp->mPacketGroup, &buffer, size); + mpp_packet_init_with_buffer(&packet, buffer); + mpp_buffer_put(buffer); + } + mpp_assert(packet); - mpp_packet_set_pts(packet, mpp_frame_get_pts(frame)); + mpp_packet_set_pts(packet, mpp_frame_get_pts(frame)); - hal_task->frame = frame; - hal_task->input = mpp_frame_get_buffer(frame); - hal_task->packet = packet; - hal_task->output = mpp_packet_get_buffer(packet); - hal_task->mv_info = mv_info; + hal_task->frame = frame; + hal_task->input = mpp_frame_get_buffer(frame); + hal_task->packet = packet; + hal_task->output = mpp_packet_get_buffer(packet); + mpp_task_meta_get_buffer(task_in, KEY_MOTION_INFO, &hal_task->mv_info); - ret = enc_impl_start(impl, hal_task); - if (ret) { - enc_dbg_detail("mpp %p enc_impl_start drop one frame", mpp); - goto TASK_END; - } - - ret = enc_impl_proc_dpb(impl, hal_task); - if (ret) { - mpp_err("mpp %p enc_impl_proc_dpb failed return %d", mpp, ret); - goto TASK_END; - } - - ret = enc_impl_proc_rc(impl, hal_task); - if (ret) { - mpp_err("mpp %p enc_impl_proc_rc failed return %d", mpp, ret); - goto TASK_END; - } - - ret = enc_impl_proc_hal(impl, hal_task); - if (ret) { - mpp_err("mpp %p enc_impl_proc_hal failed return %d", mpp, ret); - goto TASK_END; - } - - RUN_ENC_HAL_FUNC(mpp_enc_hal_get_task, hal, hal_task, mpp, ret); - RUN_ENC_HAL_FUNC(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret); - RUN_ENC_HAL_FUNC(mpp_enc_hal_start, hal, hal_task, mpp, ret); - RUN_ENC_HAL_FUNC(mpp_enc_hal_wait, hal, hal_task, mpp, ret); - RUN_ENC_HAL_FUNC(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret); - - ret = enc_impl_update_hal(impl, hal_task); - if (ret) { - mpp_err("mpp %p enc_impl_proc_hal failed return %d", mpp, ret); - goto TASK_END; - } - - ret = enc_impl_update_rc(impl, hal_task); - if (ret) { - mpp_err("mpp %p enc_impl_proc_rc failed return %d", mpp, ret); - goto TASK_END; - } - - TASK_END: - mpp_packet_set_length(packet, hal_task->length); - } else { - /* - * else init a empty packet for output - */ - mpp_packet_new(&packet); + RUN_ENC_IMPL_FUNC(enc_impl_start, impl, hal_task, mpp, ret); + /* Invalid task for frame rate drop is returned as error task */ + if (!hal_task->valid) { + hal_task->length = 0; + goto TASK_ERR; } - if (mpp_frame_get_eos(frame)) - mpp_packet_set_eos(packet); + TASK_REENCODE: + RUN_ENC_IMPL_FUNC(enc_impl_proc_dpb, impl, hal_task, mpp, ret); + RUN_ENC_IMPL_FUNC(enc_impl_proc_rc, impl, hal_task, mpp, ret); + RUN_ENC_IMPL_FUNC(enc_impl_proc_hal, impl, hal_task, mpp, ret); - /* - * first clear output packet - * then enqueue task back to input port - * final user will release the mpp_frame they had input - */ - mpp_task_meta_set_frame(task_in, KEY_INPUT_FRAME, frame); - mpp_port_enqueue(input, task_in); + RUN_ENC_HAL_FUNC(mpp_enc_hal_get_task, hal, hal_task, mpp, ret); + RUN_ENC_HAL_FUNC(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret); + RUN_ENC_HAL_FUNC(mpp_enc_hal_start, hal, hal_task, mpp, ret); + RUN_ENC_HAL_FUNC(mpp_enc_hal_wait, hal, hal_task, mpp, ret); + RUN_ENC_HAL_FUNC(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret); - // send finished task to output port - ret = mpp_port_dequeue(output, &task_out); + RUN_ENC_IMPL_FUNC(enc_impl_update_hal, impl, hal_task, mpp, ret); + RUN_ENC_IMPL_FUNC(enc_impl_update_rc, impl, hal_task, mpp, ret); + + /* If task needs reencode restart from proc_dpb */ + if (hal_task->reencode) { + mpp_log_f("reencode time %d\n"); + goto TASK_REENCODE; + } + + TASK_ERR: + mpp_packet_set_length(packet, hal_task->length); /* * task_in may be null if output port is awaken by Mpp::clear() */ - if (task_out) { - //set motion info buffer to output task - if (mv_info) - mpp_task_meta_set_buffer(task_out, KEY_MOTION_INFO, mv_info); + if (hal_task->mv_info) + mpp_task_meta_set_buffer(task_out, KEY_MOTION_INFO, hal_task->mv_info); - mpp_task_meta_set_packet(task_out, KEY_OUTPUT_PACKET, packet); + { + RK_S32 is_intra = hal_task->is_intra; + RK_U32 flag = mpp_packet_get_flag(packet); - { - RK_S32 is_intra = hal_task->is_intra; - RK_U32 flag = mpp_packet_get_flag(packet); - - mpp_task_meta_set_s32(task_out, KEY_OUTPUT_INTRA, is_intra); - if (is_intra) { - mpp_packet_set_flag(packet, flag | MPP_PACKET_FLAG_INTRA); - } + mpp_task_meta_set_s32(task_out, KEY_OUTPUT_INTRA, is_intra); + if (is_intra) { + mpp_packet_set_flag(packet, flag | MPP_PACKET_FLAG_INTRA); } - - // setup output task here - mpp_port_enqueue(output, task_out); - } else { - mpp_packet_deinit(&packet); } + TASK_RETURN: + /* + * First return output packet. + * Then enqueue task back to input port. + * Final user will release the mpp_frame they had input. + */ + if (NULL == packet) + mpp_packet_new(&packet); + + if (frame && mpp_frame_get_eos(frame)) + mpp_packet_set_eos(packet); + else + mpp_packet_clr_eos(packet); + + mpp_task_meta_set_packet(task_out, KEY_OUTPUT_PACKET, packet); + mpp_port_enqueue(output, task_out); + + mpp_task_meta_set_frame(task_in, KEY_INPUT_FRAME, frame); + mpp_port_enqueue(input, task_in); + task_in = NULL; task_out = NULL; packet = NULL; diff --git a/mpp/hal/inc/hal_task.h b/mpp/hal/inc/hal_task.h index a195832f..f17e2f97 100644 --- a/mpp/hal/inc/hal_task.h +++ b/mpp/hal/inc/hal_task.h @@ -170,6 +170,7 @@ typedef struct HalDecTask_t { typedef struct HalEncTask_t { RK_U32 valid; + RK_U32 reencode; // current tesk protocol syntax information MppSyntax syntax; @@ -191,7 +192,6 @@ typedef struct HalEncTask_t { RK_S32 temporal_id; HalEncTaskFlag flags; - } HalEncTask; typedef struct HalDecVprocTask_t {