[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_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_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 */
} MppEncMDBlkInfo;
/*
* Mpp video codec related configuration
*/
typedef struct MppEncHwCfg_t {
RK_U32 change;
RK_S32 me_search_range_x;
RK_S32 me_search_range_y;
} MppEncHwCfg;
typedef enum MppEncHeaderMode_t {
/* default mode: attach vps/sps/pps only on first frame */
MPP_ENC_HEADER_MODE_DEFAULT,
/* IDR mode: attach vps/sps/pps on each IDR frame */
MPP_ENC_HEADER_MODE_EACH_IDR,
MPP_ENC_HEADER_MODE_BUTT,
} MppEncHeaderMode;
typedef enum MppEncSeiMode_t {
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_RESET (0x00000040)
#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_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_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_reenc(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_REENC, fmt, ## __VA_ARGS__)
extern RK_U32 mpp_enc_debug;

View File

@@ -75,16 +75,18 @@ typedef struct MppEncImpl_t {
MppEncCfgSet set;
/* control process */
RK_U32 cmd_send;
RK_U32 cmd_recv;
MpiCmd cmd;
void *param;
MPP_RET *cmd_ret;
sem_t enc_ctrl;
// legacy support for MPP_ENC_GET_EXTRA_INFO
MppPacket hdr_pkt;
RK_U32 cmd_send;
RK_U32 cmd_recv;
RK_U32 hdr_need_updated;
RK_U32 hdr_len;
RK_U32 hdr_ready;
MppEncHeaderMode hdr_mode;
} MppEncImpl;
typedef union EncTaskWait_u {
@@ -120,6 +122,7 @@ typedef union EncTaskStatus_u {
RK_U32 task_out_rdy : 1;
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_restore : 1; // reenc flow start point
RK_U32 enc_proc_dpb : 1; // enc stage
@@ -235,8 +238,6 @@ static void mpp_enc_proc_cfg(MppEncImpl *enc)
switch (enc->cmd) {
case MPP_ENC_GET_HDR_SYNC :
case MPP_ENC_GET_EXTRA_INFO : {
MppPacket pkt = NULL;
/*
* NOTE: get stream header should use user's MppPacket
* 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
* 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) {
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) {
size_t size = SZ_1K;
void *ptr = mpp_calloc_size(void, size);
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;
*(MppPacket *)enc->param = enc->hdr_pkt;
} else {
mpp_packet_copy((MppPacket)enc->param, enc->hdr_pkt);
}
} break;
case MPP_ENC_GET_RC_API_ALL : {
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_updated = 1;
} 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 : {
enc_impl_proc_cfg(enc->impl, enc->cmd, enc->param);
if (MPP_ENC_SET_CODEC_CFG == enc->cmd ||
MPP_ENC_SET_PREP_CFG == enc->cmd)
enc->hdr_need_updated = 1;
MPP_ENC_SET_PREP_CFG == enc->cmd) {
enc->hdr_ready = 0;
}
} break;
}
}
@@ -610,23 +625,34 @@ void *mpp_enc_thread(void *data)
// 11. check frame drop by frame rate conversion
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);
// when the frame should be dropped just return empty packet
if (frm->drop) {
hal_task->valid = 0;
hal_task->length = 0;
goto TASK_DONE;
}
// start encoder task process here
hal_task->valid = 1;
// 12. generate header before hardware stream
if (enc->hdr_need_updated) {
enc_impl_gen_hdr(impl, packet);
enc->hdr_need_updated = 0;
if (!enc->hdr_ready) {
enc_impl_gen_hdr(impl, enc->hdr_pkt);
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",
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->input = mpp_frame_get_buffer(frame);
hal_task->packet = packet;
@@ -634,22 +660,38 @@ void *mpp_enc_thread(void *data)
hal_task->length = mpp_packet_get_length(packet);
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);
task.status.enc_backup = 1;
RUN_ENC_IMPL_FUNC(enc_impl_start, impl, hal_task, mpp, ret);
TASK_REENCODE:
// 14. 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);
}
// 15. restore and process dpb
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);
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)
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;
@@ -683,7 +725,7 @@ void *mpp_enc_thread(void *data)
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);
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;
}
@@ -802,6 +844,13 @@ MPP_RET mpp_enc_init_v2(MppEnc *enc, MppEncCfg *cfg)
p->enc_hal = enc_hal;
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 */
p->cfg.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;
}
MPP_RET ret = MPP_OK;
AutoMutex auto_lock(&enc->lock);
MPP_RET ret = MPP_OK;
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");
memcpy(param, &enc->cfg.rc, sizeof(enc->cfg.rc));
} 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 : {
// Cmd which is not get configure will handle by enc_impl
enc->cmd = cmd;
enc->param = param;
enc->cmd = cmd;
enc->param = param;
enc->cmd_ret = &ret;
enc->cmd_send++;
mpp_enc_notify_v2(ctx, MPP_ENC_CONTROL);

View File

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