mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-10-27 19:10:21 +08:00
[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 <herman.chen@rock-chips.com> Change-Id: Ibca23e03d2e82f280bb7db7cf522fb1648f840bf
This commit is contained in:
@@ -523,19 +523,18 @@ static MPP_RET h264e_start(void *ctx, HalEncTask *task)
|
|||||||
* Determine current frame which should be encoded or not according to
|
* Determine current frame which should be encoded or not according to
|
||||||
* input and output frame rate.
|
* input and output frame rate.
|
||||||
*/
|
*/
|
||||||
RK_S32 drop = rc_frm_check_drop(p->rc_ctx);
|
task->valid = !rc_frm_check_drop(p->rc_ctx);
|
||||||
if (drop)
|
if (!task->valid)
|
||||||
mpp_log_f("drop one frame\n");
|
mpp_log_f("drop one frame by fps\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Step 3: Backup dpb for reencode
|
* Step 3: Backup dpb for reencode
|
||||||
*/
|
*/
|
||||||
h264e_dpb_copy(&p->dpb_bak, &p->dpb);
|
h264e_dpb_copy(&p->dpb_bak, &p->dpb);
|
||||||
|
|
||||||
(void)task;
|
|
||||||
h264e_dbg_func("leave\n");
|
h264e_dbg_func("leave\n");
|
||||||
|
|
||||||
return (drop) ? (MPP_NOK) : (MPP_OK);
|
return MPP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MPP_RET h264e_proc_dpb(void *ctx, HalEncTask *task)
|
static MPP_RET h264e_proc_dpb(void *ctx, HalEncTask *task)
|
||||||
|
|||||||
@@ -185,11 +185,18 @@ static MPP_RET check_enc_task_wait(MppEncImpl *enc, EncTask *task)
|
|||||||
return ret;
|
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) \
|
#define RUN_ENC_HAL_FUNC(func, hal, task, mpp, ret) \
|
||||||
ret = func(hal, task); \
|
ret = func(hal, task); \
|
||||||
if (ret) { \
|
if (ret) { \
|
||||||
mpp_err("mpp %p ##func failed return %d", mpp, ret); \
|
mpp_err("mpp %p ##func failed return %d", mpp, ret); \
|
||||||
goto TASK_END; \
|
goto TASK_ERR; \
|
||||||
}
|
}
|
||||||
|
|
||||||
void *mpp_enc_thread(void *data)
|
void *mpp_enc_thread(void *data)
|
||||||
@@ -209,7 +216,7 @@ void *mpp_enc_thread(void *data)
|
|||||||
MPP_RET ret = MPP_OK;
|
MPP_RET ret = MPP_OK;
|
||||||
MppFrame frame = NULL;
|
MppFrame frame = NULL;
|
||||||
MppPacket packet = NULL;
|
MppPacket packet = NULL;
|
||||||
MppBuffer mv_info = NULL;
|
MppBuffer frm_buf = NULL;
|
||||||
|
|
||||||
memset(&task, 0, sizeof(task));
|
memset(&task, 0, sizeof(task));
|
||||||
|
|
||||||
@@ -303,17 +310,27 @@ void *mpp_enc_thread(void *data)
|
|||||||
}
|
}
|
||||||
enc_dbg_detail("task out ready\n");
|
enc_dbg_detail("task out ready\n");
|
||||||
|
|
||||||
|
// get tasks from both input and output
|
||||||
ret = mpp_port_dequeue(input, &task_in);
|
ret = mpp_port_dequeue(input, &task_in);
|
||||||
mpp_assert(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_frame (task_in, KEY_INPUT_FRAME, &frame);
|
||||||
mpp_task_meta_get_packet(task_in, KEY_OUTPUT_PACKET, &packet);
|
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) {
|
/* If there is no input frame just return empty packet task */
|
||||||
mpp_port_enqueue(input, task_in);
|
if (NULL == frame)
|
||||||
continue;
|
goto TASK_RETURN;
|
||||||
}
|
|
||||||
|
frm_buf = mpp_frame_get_buffer(frame);
|
||||||
|
if (NULL == frm_buf)
|
||||||
|
goto TASK_RETURN;
|
||||||
|
|
||||||
reset_hal_enc_task(hal_task);
|
reset_hal_enc_task(hal_task);
|
||||||
|
|
||||||
@@ -322,122 +339,96 @@ void *mpp_enc_thread(void *data)
|
|||||||
enc->hdr_need_updated = 0;
|
enc->hdr_need_updated = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpp_frame_get_buffer(frame)) {
|
/*
|
||||||
/*
|
* if there is available buffer in the input frame do encoding
|
||||||
* if there is available buffer in the input frame do encoding
|
*/
|
||||||
*/
|
if (NULL == packet) {
|
||||||
if (NULL == packet) {
|
RK_U32 width = enc->cfg.prep.width;
|
||||||
RK_U32 width = enc->cfg.prep.width;
|
RK_U32 height = enc->cfg.prep.height;
|
||||||
RK_U32 height = enc->cfg.prep.height;
|
RK_U32 size = width * height;
|
||||||
RK_U32 size = width * height;
|
MppBuffer buffer = NULL;
|
||||||
MppBuffer buffer = NULL;
|
|
||||||
|
|
||||||
mpp_assert(size);
|
mpp_assert(size);
|
||||||
mpp_buffer_get(mpp->mPacketGroup, &buffer, size);
|
mpp_buffer_get(mpp->mPacketGroup, &buffer, size);
|
||||||
mpp_packet_init_with_buffer(&packet, buffer);
|
mpp_packet_init_with_buffer(&packet, buffer);
|
||||||
mpp_buffer_put(buffer);
|
mpp_buffer_put(buffer);
|
||||||
}
|
}
|
||||||
mpp_assert(packet);
|
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->frame = frame;
|
||||||
hal_task->input = mpp_frame_get_buffer(frame);
|
hal_task->input = mpp_frame_get_buffer(frame);
|
||||||
hal_task->packet = packet;
|
hal_task->packet = packet;
|
||||||
hal_task->output = mpp_packet_get_buffer(packet);
|
hal_task->output = mpp_packet_get_buffer(packet);
|
||||||
hal_task->mv_info = mv_info;
|
mpp_task_meta_get_buffer(task_in, KEY_MOTION_INFO, &hal_task->mv_info);
|
||||||
|
|
||||||
ret = enc_impl_start(impl, hal_task);
|
RUN_ENC_IMPL_FUNC(enc_impl_start, impl, hal_task, mpp, ret);
|
||||||
if (ret) {
|
/* Invalid task for frame rate drop is returned as error task */
|
||||||
enc_dbg_detail("mpp %p enc_impl_start drop one frame", mpp);
|
if (!hal_task->valid) {
|
||||||
goto TASK_END;
|
hal_task->length = 0;
|
||||||
}
|
goto TASK_ERR;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpp_frame_get_eos(frame))
|
TASK_REENCODE:
|
||||||
mpp_packet_set_eos(packet);
|
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);
|
||||||
|
|
||||||
/*
|
RUN_ENC_HAL_FUNC(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
|
||||||
* first clear output packet
|
RUN_ENC_HAL_FUNC(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
|
||||||
* then enqueue task back to input port
|
RUN_ENC_HAL_FUNC(mpp_enc_hal_start, hal, hal_task, mpp, ret);
|
||||||
* final user will release the mpp_frame they had input
|
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);
|
||||||
mpp_task_meta_set_frame(task_in, KEY_INPUT_FRAME, frame);
|
|
||||||
mpp_port_enqueue(input, task_in);
|
|
||||||
|
|
||||||
// send finished task to output port
|
RUN_ENC_IMPL_FUNC(enc_impl_update_hal, impl, hal_task, mpp, ret);
|
||||||
ret = mpp_port_dequeue(output, &task_out);
|
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()
|
* task_in may be null if output port is awaken by Mpp::clear()
|
||||||
*/
|
*/
|
||||||
if (task_out) {
|
if (hal_task->mv_info)
|
||||||
//set motion info buffer to output task
|
mpp_task_meta_set_buffer(task_out, KEY_MOTION_INFO, hal_task->mv_info);
|
||||||
if (mv_info)
|
|
||||||
mpp_task_meta_set_buffer(task_out, KEY_MOTION_INFO, 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);
|
||||||
|
|
||||||
{
|
mpp_task_meta_set_s32(task_out, KEY_OUTPUT_INTRA, is_intra);
|
||||||
RK_S32 is_intra = hal_task->is_intra;
|
if (is_intra) {
|
||||||
RK_U32 flag = mpp_packet_get_flag(packet);
|
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_in = NULL;
|
||||||
task_out = NULL;
|
task_out = NULL;
|
||||||
packet = NULL;
|
packet = NULL;
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ typedef struct HalDecTask_t {
|
|||||||
|
|
||||||
typedef struct HalEncTask_t {
|
typedef struct HalEncTask_t {
|
||||||
RK_U32 valid;
|
RK_U32 valid;
|
||||||
|
RK_U32 reencode;
|
||||||
|
|
||||||
// current tesk protocol syntax information
|
// current tesk protocol syntax information
|
||||||
MppSyntax syntax;
|
MppSyntax syntax;
|
||||||
@@ -191,7 +192,6 @@ typedef struct HalEncTask_t {
|
|||||||
RK_S32 temporal_id;
|
RK_S32 temporal_id;
|
||||||
|
|
||||||
HalEncTaskFlag flags;
|
HalEncTaskFlag flags;
|
||||||
|
|
||||||
} HalEncTask;
|
} HalEncTask;
|
||||||
|
|
||||||
typedef struct HalDecVprocTask_t {
|
typedef struct HalDecVprocTask_t {
|
||||||
|
|||||||
Reference in New Issue
Block a user