[mpp_enc_v2]: Add encoder header output mode

1. Default output mode is output header only on config changed.
2. Add new mode to output header on each intra frame.

Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
Change-Id: Iea8dd1e6bb377318b88300d6a013f2c736b15afc
This commit is contained in:
Herman Chen
2020-03-30 15:25:27 +08:00
parent 6aac71a463
commit 0a2d4e341c
5 changed files with 105 additions and 45 deletions

View File

@@ -164,6 +164,8 @@ typedef enum {
MPP_ENC_CFG_MJPEG = CMD_MODULE_CODEC | CMD_CTX_ID_ENC | CMD_ENC_CFG_MJPEG, MPP_ENC_CFG_MJPEG = CMD_MODULE_CODEC | CMD_CTX_ID_ENC | CMD_ENC_CFG_MJPEG,
MPP_ENC_CFG_MISC = CMD_MODULE_CODEC | CMD_CTX_ID_ENC | CMD_ENC_CFG_MISC, MPP_ENC_CFG_MISC = CMD_MODULE_CODEC | CMD_CTX_ID_ENC | CMD_ENC_CFG_MISC,
MPP_ENC_SET_HEADER_MODE, /* set MppEncHeaderMode */
MPP_ENC_GET_HEADER_MODE, /* get MppEncHeaderMode */
MPP_ENC_CFG_SPLIT = CMD_MODULE_CODEC | CMD_CTX_ID_ENC | CMD_ENC_CFG_SPLIT, MPP_ENC_CFG_SPLIT = CMD_MODULE_CODEC | CMD_CTX_ID_ENC | CMD_ENC_CFG_SPLIT,
MPP_ENC_SET_SPLIT, /* set MppEncSliceSplit structure */ MPP_ENC_SET_SPLIT, /* set MppEncSliceSplit structure */

View File

@@ -394,14 +394,13 @@ typedef struct MppEncMDBlkInfo_t {
RK_S32 mvy : 8; /* bit 24~31 - signed vertical mv */ RK_S32 mvy : 8; /* bit 24~31 - signed vertical mv */
} MppEncMDBlkInfo; } MppEncMDBlkInfo;
/* typedef enum MppEncHeaderMode_t {
* Mpp video codec related configuration /* default mode: attach vps/sps/pps only on first frame */
*/ MPP_ENC_HEADER_MODE_DEFAULT,
typedef struct MppEncHwCfg_t { /* IDR mode: attach vps/sps/pps on each IDR frame */
RK_U32 change; MPP_ENC_HEADER_MODE_EACH_IDR,
RK_S32 me_search_range_x; MPP_ENC_HEADER_MODE_BUTT,
RK_S32 me_search_range_y; } MppEncHeaderMode;
} MppEncHwCfg;
typedef enum MppEncSeiMode_t { typedef enum MppEncSeiMode_t {
MPP_ENC_SEI_MODE_DISABLE, /* default mode, SEI writing is disabled */ MPP_ENC_SEI_MODE_DISABLE, /* default mode, SEI writing is disabled */

View File

@@ -25,6 +25,7 @@
#define MPP_ENC_DBG_DETAIL (0x00000020) #define MPP_ENC_DBG_DETAIL (0x00000020)
#define MPP_ENC_DBG_RESET (0x00000040) #define MPP_ENC_DBG_RESET (0x00000040)
#define MPP_ENC_DBG_NOTIFY (0x00000080) #define MPP_ENC_DBG_NOTIFY (0x00000080)
#define MPP_ENC_DBG_REENC (0x00000100)
#define mpp_enc_dbg(flag, fmt, ...) _mpp_dbg(mpp_enc_debug, flag, fmt, ## __VA_ARGS__) #define mpp_enc_dbg(flag, fmt, ...) _mpp_dbg(mpp_enc_debug, flag, fmt, ## __VA_ARGS__)
#define mpp_enc_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpp_enc_debug, flag, fmt, ## __VA_ARGS__) #define mpp_enc_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpp_enc_debug, flag, fmt, ## __VA_ARGS__)
@@ -34,6 +35,7 @@
#define enc_dbg_status(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_STATUS, fmt, ## __VA_ARGS__) #define enc_dbg_status(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_STATUS, fmt, ## __VA_ARGS__)
#define enc_dbg_detail(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_DETAIL, fmt, ## __VA_ARGS__) #define enc_dbg_detail(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_DETAIL, fmt, ## __VA_ARGS__)
#define enc_dbg_notify(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_NOTIFY, fmt, ## __VA_ARGS__) #define enc_dbg_notify(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_NOTIFY, fmt, ## __VA_ARGS__)
#define enc_dbg_reenc(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_REENC, fmt, ## __VA_ARGS__)
extern RK_U32 mpp_enc_debug; extern RK_U32 mpp_enc_debug;

View File

@@ -75,16 +75,18 @@ typedef struct MppEncImpl_t {
MppEncCfgSet set; MppEncCfgSet set;
/* control process */ /* control process */
RK_U32 cmd_send;
RK_U32 cmd_recv;
MpiCmd cmd; MpiCmd cmd;
void *param; void *param;
MPP_RET *cmd_ret;
sem_t enc_ctrl; sem_t enc_ctrl;
// legacy support for MPP_ENC_GET_EXTRA_INFO // legacy support for MPP_ENC_GET_EXTRA_INFO
MppPacket hdr_pkt; MppPacket hdr_pkt;
RK_U32 hdr_len;
RK_U32 cmd_send; RK_U32 hdr_ready;
RK_U32 cmd_recv; MppEncHeaderMode hdr_mode;
RK_U32 hdr_need_updated;
} MppEncImpl; } MppEncImpl;
typedef union EncTaskWait_u { typedef union EncTaskWait_u {
@@ -120,6 +122,7 @@ typedef union EncTaskStatus_u {
RK_U32 task_out_rdy : 1; RK_U32 task_out_rdy : 1;
RK_U32 rc_check_frm_drop : 1; // rc stage RK_U32 rc_check_frm_drop : 1; // rc stage
RK_U32 enc_add_header : 1; // write header before encoding
RK_U32 enc_backup : 1; // enc stage RK_U32 enc_backup : 1; // enc stage
RK_U32 enc_restore : 1; // reenc flow start point RK_U32 enc_restore : 1; // reenc flow start point
RK_U32 enc_proc_dpb : 1; // enc stage RK_U32 enc_proc_dpb : 1; // enc stage
@@ -235,8 +238,6 @@ static void mpp_enc_proc_cfg(MppEncImpl *enc)
switch (enc->cmd) { switch (enc->cmd) {
case MPP_ENC_GET_HDR_SYNC : case MPP_ENC_GET_HDR_SYNC :
case MPP_ENC_GET_EXTRA_INFO : { case MPP_ENC_GET_EXTRA_INFO : {
MppPacket pkt = NULL;
/* /*
* NOTE: get stream header should use user's MppPacket * NOTE: get stream header should use user's MppPacket
* If we provide internal MppPacket to external user * If we provide internal MppPacket to external user
@@ -244,23 +245,20 @@ static void mpp_enc_proc_cfg(MppEncImpl *enc)
* So encoder always write its header to external buffer * So encoder always write its header to external buffer
* which is provided by user. * which is provided by user.
*/ */
if (!enc->hdr_ready) {
enc_impl_gen_hdr(enc->impl, enc->hdr_pkt);
enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt);
enc->hdr_ready = 1;
}
if (enc->cmd == MPP_ENC_GET_EXTRA_INFO) { if (enc->cmd == MPP_ENC_GET_EXTRA_INFO) {
mpp_err("Please use MPP_ENC_GET_HDR_SYNC instead of unsafe MPP_ENC_GET_EXTRA_INFO\n"); mpp_err("Please use MPP_ENC_GET_HDR_SYNC instead of unsafe MPP_ENC_GET_EXTRA_INFO\n");
mpp_err("NOTE: MPP_ENC_GET_HDR_SYNC needs MppPacket input\n");
if (NULL == enc->hdr_pkt) { *(MppPacket *)enc->param = enc->hdr_pkt;
size_t size = SZ_1K; } else {
void *ptr = mpp_calloc_size(void, size); mpp_packet_copy((MppPacket)enc->param, enc->hdr_pkt);
}
mpp_packet_init(&enc->hdr_pkt, ptr, size);
}
pkt = enc->hdr_pkt;
*(MppPacket *)enc->param = pkt;
} else
pkt = (MppPacket)enc->param;
enc_impl_gen_hdr(enc->impl, pkt);
enc->hdr_need_updated = 0;
} break; } break;
case MPP_ENC_GET_RC_API_ALL : { case MPP_ENC_GET_RC_API_ALL : {
RcApiQueryAll *query = (RcApiQueryAll *)enc->param; RcApiQueryAll *query = (RcApiQueryAll *)enc->param;
@@ -290,11 +288,28 @@ static void mpp_enc_proc_cfg(MppEncImpl *enc)
enc->rc_status.rc_api_user_cfg = 1; enc->rc_status.rc_api_user_cfg = 1;
enc->rc_status.rc_api_updated = 1; enc->rc_status.rc_api_updated = 1;
} break; } break;
case MPP_ENC_SET_HEADER_MODE : {
if (enc->param) {
MppEncHeaderMode mode = *((MppEncHeaderMode *)enc->param);
if (mode < MPP_ENC_HEADER_MODE_BUTT) {
enc->hdr_mode = mode;
enc_dbg_ctrl("header mode set to %d\n", mode);
} else {
mpp_err_f("invalid header mode %d\n", mode);
*enc->cmd_ret = MPP_NOK;
}
} else {
mpp_err_f("invalid NULL ptr on setting header mode\n");
*enc->cmd_ret = MPP_NOK;
}
} break;
default : { default : {
enc_impl_proc_cfg(enc->impl, enc->cmd, enc->param); enc_impl_proc_cfg(enc->impl, enc->cmd, enc->param);
if (MPP_ENC_SET_CODEC_CFG == enc->cmd || if (MPP_ENC_SET_CODEC_CFG == enc->cmd ||
MPP_ENC_SET_PREP_CFG == enc->cmd) MPP_ENC_SET_PREP_CFG == enc->cmd) {
enc->hdr_need_updated = 1; enc->hdr_ready = 0;
}
} break; } break;
} }
} }
@@ -610,23 +625,34 @@ void *mpp_enc_thread(void *data)
// 11. check frame drop by frame rate conversion // 11. check frame drop by frame rate conversion
RUN_ENC_RC_FUNC(rc_frm_check_drop, enc->rc_ctx, rc_task, mpp, ret); RUN_ENC_RC_FUNC(rc_frm_check_drop, enc->rc_ctx, rc_task, mpp, ret);
task.status.rc_check_frm_drop = 1;
enc_dbg_detail("task %d drop %d\n", frm->seq_idx, frm->drop); enc_dbg_detail("task %d drop %d\n", frm->seq_idx, frm->drop);
// when the frame should be dropped just return empty packet
if (frm->drop) { if (frm->drop) {
hal_task->valid = 0; hal_task->valid = 0;
hal_task->length = 0; hal_task->length = 0;
goto TASK_DONE; goto TASK_DONE;
} }
// start encoder task process here
hal_task->valid = 1; hal_task->valid = 1;
// 12. generate header before hardware stream // 12. generate header before hardware stream
if (enc->hdr_need_updated) { if (!enc->hdr_ready) {
enc_impl_gen_hdr(impl, packet); enc_impl_gen_hdr(impl, enc->hdr_pkt);
enc->hdr_need_updated = 0; enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt);
enc->hdr_ready = 1;
hal_task->header_length = enc->hdr_len;
enc_dbg_detail("task %d update header length %d\n", enc_dbg_detail("task %d update header length %d\n",
frm->seq_idx, mpp_packet_get_length(packet)); frm->seq_idx, hal_task->header_length);
mpp_packet_copy(packet, enc->hdr_pkt);
task.status.enc_add_header = 1;
} }
// 13. setup input frame and output packet
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;
@@ -634,22 +660,38 @@ void *mpp_enc_thread(void *data)
hal_task->length = mpp_packet_get_length(packet); hal_task->length = mpp_packet_get_length(packet);
mpp_task_meta_get_buffer(task_in, KEY_MOTION_INFO, &hal_task->mv_info); mpp_task_meta_get_buffer(task_in, KEY_MOTION_INFO, &hal_task->mv_info);
// 13. backup dpb // 14. backup dpb
enc_dbg_detail("task %d enc start\n", frm->seq_idx); enc_dbg_detail("task %d enc start\n", frm->seq_idx);
task.status.enc_backup = 1;
RUN_ENC_IMPL_FUNC(enc_impl_start, impl, hal_task, mpp, ret); RUN_ENC_IMPL_FUNC(enc_impl_start, impl, hal_task, mpp, ret);
TASK_REENCODE: TASK_REENCODE:
// 14. restore and process dpb // 15. restore and process dpb
if (!frm->reencode || frm->re_dpb_proc) {
enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
RUN_ENC_IMPL_FUNC(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
}
if (!frm->reencode) { if (!frm->reencode) {
if (!frm->re_dpb_proc) {
enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
RUN_ENC_IMPL_FUNC(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
}
enc_dbg_detail("task %d rc frame start\n", frm->seq_idx); enc_dbg_detail("task %d rc frame start\n", frm->seq_idx);
RUN_ENC_RC_FUNC(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret); RUN_ENC_RC_FUNC(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret);
task.status.enc_proc_dpb = 1;
if (frm->re_dpb_proc) if (frm->re_dpb_proc)
goto TASK_REENCODE; goto TASK_REENCODE;
// 16. generate header before hardware stream
if (enc->hdr_mode == MPP_ENC_HEADER_MODE_EACH_IDR &&
frm->is_intra && !task.status.enc_add_header) {
enc_dbg_detail("task %d IDR header length %d\n",
frm->seq_idx, enc->hdr_len);
mpp_packet_copy(packet, enc->hdr_pkt);
task.status.enc_add_header = 1;
hal_task->header_length = enc->hdr_len;
hal_task->length += enc->hdr_len;
}
} }
frm->reencode = 0; frm->reencode = 0;
@@ -683,7 +725,7 @@ void *mpp_enc_thread(void *data)
enc_dbg_detail("task %d rc frame end\n", frm->seq_idx); enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
RUN_ENC_RC_FUNC(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret); RUN_ENC_RC_FUNC(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
if (frm->reencode) { if (frm->reencode) {
mpp_log_f("reencode time %d\n", frm->reencode_times); enc_dbg_reenc("reencode time %d\n", frm->reencode_times);
goto TASK_REENCODE; goto TASK_REENCODE;
} }
@@ -802,6 +844,13 @@ MPP_RET mpp_enc_init_v2(MppEnc *enc, MppEncCfg *cfg)
p->enc_hal = enc_hal; p->enc_hal = enc_hal;
p->mpp = cfg->mpp; p->mpp = cfg->mpp;
{ // create header packet storage
size_t size = SZ_1K;
void *ptr = mpp_calloc_size(void, size);
mpp_packet_init(&p->hdr_pkt, ptr, size);
}
/* NOTE: setup configure coding for check */ /* NOTE: setup configure coding for check */
p->cfg.codec.coding = coding; p->cfg.codec.coding = coding;
p->set.codec.coding = coding; p->set.codec.coding = coding;
@@ -944,8 +993,8 @@ MPP_RET mpp_enc_control_v2(MppEnc ctx, MpiCmd cmd, void *param)
return MPP_ERR_NULL_PTR; return MPP_ERR_NULL_PTR;
} }
MPP_RET ret = MPP_OK;
AutoMutex auto_lock(&enc->lock); AutoMutex auto_lock(&enc->lock);
MPP_RET ret = MPP_OK;
enc_dbg_ctrl("sending cmd %d param %p\n", cmd, param); enc_dbg_ctrl("sending cmd %d param %p\n", cmd, param);
@@ -962,10 +1011,15 @@ MPP_RET mpp_enc_control_v2(MppEnc ctx, MpiCmd cmd, void *param)
enc_dbg_ctrl("get rc config\n"); enc_dbg_ctrl("get rc config\n");
memcpy(param, &enc->cfg.rc, sizeof(enc->cfg.rc)); memcpy(param, &enc->cfg.rc, sizeof(enc->cfg.rc));
} break; } break;
case MPP_ENC_GET_HEADER_MODE : {
enc_dbg_ctrl("get header mode\n");
memcpy(param, &enc->hdr_mode, sizeof(enc->hdr_mode));
} break;
default : { default : {
// Cmd which is not get configure will handle by enc_impl // Cmd which is not get configure will handle by enc_impl
enc->cmd = cmd; enc->cmd = cmd;
enc->param = param; enc->param = param;
enc->cmd_ret = &ret;
enc->cmd_send++; enc->cmd_send++;
mpp_enc_notify_v2(ctx, MPP_ENC_CONTROL); mpp_enc_notify_v2(ctx, MPP_ENC_CONTROL);

View File

@@ -45,6 +45,9 @@ typedef struct HalEncTask_t {
// current tesk output stream buffer // current tesk output stream buffer
MppPacket packet; MppPacket packet;
MppBuffer output; MppBuffer output;
RK_U32 header_length;
RK_U32 sei_length;
RK_U32 hw_length;
RK_U32 length; RK_U32 length;
// current tesk input slot buffer // current tesk input slot buffer