mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-10-05 01:02:39 +08:00
[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:
@@ -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 */
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user