msm: vidc: Add support for Hier-B

Add support for Hier-B.

Change-Id: I2bd6f1b6525224795500d8a260de3d78a78d2163
CRs-Fixed: 2637948
Signed-off-by: Amit Shekhar <ashekhar@codeaurora.org>
This commit is contained in:
Amit Shekhar 2020-05-28 10:14:58 -07:00
commit 911dc56174
5 changed files with 194 additions and 44 deletions

View file

@ -601,10 +601,11 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE,
.name = "Set Hier coding type",
.type = V4L2_CTRL_TYPE_MENU,
.minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
.minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
.maximum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
.default_value = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
.menu_skip_mask = ~(
(1 << V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) |
(1 << V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P)
),
.qmenu = NULL,
@ -2451,8 +2452,14 @@ int msm_venc_set_intra_period(struct msm_vidc_inst *inst)
{
int rc = 0;
struct hfi_device *hdev;
struct v4l2_ctrl *ctrl;
struct v4l2_ctrl *gop_size = NULL;
struct v4l2_ctrl *bframes = NULL;
struct v4l2_ctrl *max_layer = NULL;
struct v4l2_ctrl *frame_t = NULL;
struct hfi_intra_period intra_period;
struct hfi_adaptive_p_b_intra_period adaptive_p_b_intra_period;
u32 codec;
bool adaptive_bframes = false;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
@ -2460,38 +2467,78 @@ int msm_venc_set_intra_period(struct msm_vidc_inst *inst)
}
hdev = inst->core->device;
msm_venc_adjust_gop_size(inst);
frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE);
gop_size = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_GOP_SIZE);
max_layer = get_ctrl(inst,
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
codec = get_v4l2_codec(inst);
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_GOP_SIZE);
intra_period.pframes = ctrl->val;
if (!max_layer->val && codec == V4L2_PIX_FMT_H264) {
intra_period.pframes = gop_size->val;
/*
* At this point we've already made decision on bframe.
* Control value gives updated bframe value.
*/
bframes = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES);
intra_period.bframes = bframes->val;
if (intra_period.bframes)
adaptive_bframes = true;
}
/*
* At this point we have already made decision on bframe
* Control value gives updated bframe value.
*/
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES);
intra_period.bframes = ctrl->val;
if (max_layer->val > 1) {
if (frame_t->val ==
V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) {
if (codec == V4L2_PIX_FMT_HEVC) {
adaptive_p_b_intra_period.nframes =
gop_size->val;
adaptive_bframes = true;
} else {
d_vpr_e("%s: Hier-B supported for HEVC only\n",
__func__);
return -EINVAL;
}
} else if (frame_t->val ==
V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P) {
msm_venc_adjust_gop_size(inst);
intra_period.pframes = gop_size->val;
intra_period.bframes = 0;
adaptive_bframes = false;
}
}
if (inst->state == MSM_VIDC_START_DONE &&
!intra_period.pframes && !intra_period.bframes) {
!intra_period.pframes && !intra_period.bframes) {
s_vpr_h(inst->sid,
"%s: Switch from IPPP to All Intra is not allowed\n",
__func__);
return rc;
}
s_vpr_h(inst->sid, "%s: %d %d\n", __func__, intra_period.pframes,
intra_period.bframes);
rc = call_hfi_op(hdev, session_set_property, inst->session,
HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD, &intra_period,
sizeof(intra_period));
if (frame_t->val ==
V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B &&
codec == V4L2_PIX_FMT_HEVC) {
s_vpr_h(inst->sid, "%s: nframes: %d\n",
__func__, adaptive_p_b_intra_period.nframes);
rc = call_hfi_op(hdev, session_set_property, inst->session,
HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD,
&adaptive_p_b_intra_period,
sizeof(adaptive_p_b_intra_period));
} else {
s_vpr_h(inst->sid, "%s: pframes: %d bframes: %d\n",
__func__, intra_period.pframes,
intra_period.bframes);
rc = call_hfi_op(hdev, session_set_property, inst->session,
HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD,
&intra_period, sizeof(intra_period));
}
if (rc) {
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
return rc;
}
if (intra_period.bframes) {
/* Enable adaptive bframes as nbframes!= 0 */
if (adaptive_bframes) {
rc = msm_venc_set_adaptive_bframes(inst);
if (rc) {
s_vpr_e(inst->sid, "%s: set property failed\n",
@ -2499,6 +2546,7 @@ int msm_venc_set_intra_period(struct msm_vidc_inst *inst)
return rc;
}
}
return rc;
}
@ -2764,14 +2812,14 @@ int msm_venc_set_layer_bitrate(struct msm_vidc_inst *inst)
if (!max_layer->val || !layer->val) {
s_vpr_h(inst->sid,
"%s: Hierp layer not set. Ignore layer bitrate\n",
"%s: Hier-P layer not set. Ignore layer bitrate\n",
__func__);
goto error;
}
if (max_layer->val < layer->val) {
s_vpr_h(inst->sid,
"%s: Hierp layer greater than max isn't allowed\n",
"%s: Hier-P layer greater than max isn't allowed\n",
__func__);
goto error;
}
@ -3611,7 +3659,7 @@ int msm_venc_set_base_layer_priority_id(struct msm_vidc_inst *inst)
max_layer = get_ctrl(inst,
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
if (max_layer->val <= 0) {
s_vpr_h(inst->sid, "%s: Layer id can only be set with Hierp\n",
s_vpr_h(inst->sid, "%s: Layer id can only be set with Hier-P\n",
__func__);
return 0;
}
@ -3629,11 +3677,54 @@ int msm_venc_set_base_layer_priority_id(struct msm_vidc_inst *inst)
return rc;
}
int msm_venc_set_hb_max_layer(struct msm_vidc_inst *inst)
{
int rc = 0;
struct hfi_device *hdev;
struct v4l2_ctrl *frame_t = NULL;
struct v4l2_ctrl *max_layer = NULL;
u32 hb_layer = 0;
u32 codec;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
return -EINVAL;
}
hdev = inst->core->device;
codec = get_v4l2_codec(inst);
if (codec != V4L2_PIX_FMT_HEVC)
return 0;
max_layer = get_ctrl(inst,
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE);
if (max_layer->val < 2 ||
frame_t->val != V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) {
s_vpr_h(inst->sid,
"%s: Hier-B not requested for this session\n",
__func__);
return 0;
}
hb_layer = max_layer->val - 1;
s_vpr_h(inst->sid, "%s: Hier-B max layer: %d\n",
__func__, hb_layer);
rc = call_hfi_op(hdev, session_set_property, inst->session,
HFI_PROPERTY_PARAM_VENC_HIER_B_MAX_NUM_ENH_LAYER,
&hb_layer, sizeof(hb_layer));
if (rc)
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
return rc;
}
int msm_venc_set_hp_max_layer(struct msm_vidc_inst *inst)
{
int rc = 0;
struct hfi_device *hdev;
struct v4l2_ctrl *ctrl;
struct v4l2_ctrl *frame_t = NULL;
struct v4l2_ctrl *max_layer = NULL;
u32 hp_layer = 0;
u32 codec;
@ -3647,12 +3738,20 @@ int msm_venc_set_hp_max_layer(struct msm_vidc_inst *inst)
if (codec != V4L2_PIX_FMT_H264 && codec != V4L2_PIX_FMT_HEVC)
return 0;
ctrl = get_ctrl(inst,
max_layer = get_ctrl(inst,
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE);
if (max_layer->val < 2 ||
frame_t->val != V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P) {
s_vpr_h(inst->sid,
"%s: Hier-P not requested for this session\n",
__func__);
return 0;
}
rc = msm_venc_enable_hybrid_hp(inst);
if (rc) {
s_vpr_e(inst->sid, "%s: get hybrid hp decision failed\n",
s_vpr_e(inst->sid, "%s: get hybrid hier-P decision failed\n",
__func__);
return rc;
}
@ -3661,17 +3760,17 @@ int msm_venc_set_hp_max_layer(struct msm_vidc_inst *inst)
* We send enhancement layer count to FW,
* hence, input 0/1 indicates absence of layer encoding.
*/
if (ctrl->val)
hp_layer = ctrl->val - 1;
if (max_layer->val)
hp_layer = max_layer->val - 1;
if (inst->hybrid_hp) {
s_vpr_h(inst->sid, "%s: Hybrid hierp layer: %d\n",
s_vpr_h(inst->sid, "%s: Hybrid hier-P layer: %d\n",
__func__, hp_layer);
rc = call_hfi_op(hdev, session_set_property, inst->session,
HFI_PROPERTY_PARAM_VENC_HIER_P_HYBRID_MODE,
&hp_layer, sizeof(hp_layer));
} else {
s_vpr_h(inst->sid, "%s: Hierp max layer: %d\n",
s_vpr_h(inst->sid, "%s: Hier-P max layer: %d\n",
__func__, hp_layer);
rc = call_hfi_op(hdev, session_set_property, inst->session,
HFI_PROPERTY_PARAM_VENC_HIER_P_MAX_NUM_ENH_LAYER,
@ -3686,6 +3785,7 @@ int msm_venc_set_hp_layer(struct msm_vidc_inst *inst)
{
int rc = 0;
struct hfi_device *hdev;
struct v4l2_ctrl *frame_t = NULL;
struct v4l2_ctrl *ctrl = NULL;
struct v4l2_ctrl *max_layer = NULL;
u32 hp_layer = 0;
@ -3697,6 +3797,14 @@ int msm_venc_set_hp_layer(struct msm_vidc_inst *inst)
}
hdev = inst->core->device;
frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE);
if (frame_t->val != V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P) {
s_vpr_h(inst->sid,
"%s: Hier-P layer can be set for P type frame only\n",
__func__);
return 0;
}
codec = get_v4l2_codec(inst);
if (codec != V4L2_PIX_FMT_H264 && codec != V4L2_PIX_FMT_HEVC)
return 0;
@ -3728,7 +3836,7 @@ int msm_venc_set_hp_layer(struct msm_vidc_inst *inst)
if (ctrl->val)
hp_layer = ctrl->val - 1;
s_vpr_h(inst->sid, "%s: Hierp enhancement layer: %d\n",
s_vpr_h(inst->sid, "%s: Hier-P enhancement layer: %d\n",
__func__, hp_layer);
rc = call_hfi_op(hdev, session_set_property, inst->session,
HFI_PROPERTY_CONFIG_VENC_HIER_P_ENH_LAYER,
@ -4735,6 +4843,9 @@ int msm_venc_set_properties(struct msm_vidc_inst *inst)
if (rc)
goto exit;
rc = msm_venc_set_ltr_mode(inst);
if (rc)
goto exit;
rc = msm_venc_set_hb_max_layer(inst);
if (rc)
goto exit;
rc = msm_venc_set_hp_max_layer(inst);

View file

@ -35,6 +35,7 @@ int msm_venc_set_ltr_markframe(struct msm_vidc_inst *inst);
int msm_venc_set_dyn_qp(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl);
int msm_venc_set_request_keyframe(struct msm_vidc_inst *inst);
int msm_venc_set_intra_refresh_mode(struct msm_vidc_inst *inst);
int msm_venc_set_hb_max_layer(struct msm_vidc_inst *inst);
int msm_venc_set_hp_max_layer(struct msm_vidc_inst *inst);
int msm_venc_set_hp_layer(struct msm_vidc_inst *inst);
int msm_venc_set_base_layer_priority_id(struct msm_vidc_inst *inst);

View file

@ -465,10 +465,11 @@ int msm_vidc_get_decoder_internal_buffer_sizes(struct msm_vidc_inst *inst)
int msm_vidc_get_num_ref_frames(struct msm_vidc_inst *inst)
{
int num_ref = 1;
int num_bframes = -1, ltr_count = -1, num_hp_layers;
struct v4l2_ctrl *bframe_ctrl;
struct v4l2_ctrl *ltr_ctrl;
struct v4l2_ctrl *layer_ctrl;
int num_bframes = -1, ltr_count = -1;
struct v4l2_ctrl *bframe_ctrl = NULL;
struct v4l2_ctrl *ltr_ctrl = NULL;
struct v4l2_ctrl *frame_t = NULL;
struct v4l2_ctrl *max_layer = NULL;
u32 codec;
bframe_ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES);
@ -482,21 +483,27 @@ int msm_vidc_get_num_ref_frames(struct msm_vidc_inst *inst)
if (ltr_count > 0)
num_ref = num_ref + ltr_count;
layer_ctrl = get_ctrl(inst,
frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE);
max_layer = get_ctrl(inst,
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
num_hp_layers = layer_ctrl->val;
codec = get_v4l2_codec(inst);
if (num_hp_layers > 0) {
if (frame_t->val == V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P &&
max_layer->val > 0) {
codec = get_v4l2_codec(inst);
/* LTR and B - frame not supported with hybrid HP */
if (inst->hybrid_hp)
num_ref = (num_hp_layers - 1);
num_ref = (max_layer->val - 1);
else if (codec == V4L2_PIX_FMT_HEVC)
num_ref = ((num_hp_layers + 1) / 2) + ltr_count;
else if ((codec == V4L2_PIX_FMT_H264) && (num_hp_layers <= 4))
num_ref = ((1 << (num_hp_layers - 1)) - 1) + ltr_count;
num_ref = ((max_layer->val + 1) / 2) + ltr_count;
else if ((codec == V4L2_PIX_FMT_H264) && (max_layer->val <= 4))
num_ref = ((1 << (max_layer->val - 1)) - 1) + ltr_count;
else
num_ref = ((num_hp_layers + 1) / 2) + ltr_count;
num_ref = ((max_layer->val + 1) / 2) + ltr_count;
}
if (is_hier_b_session(inst)) {
num_ref = (1 << (max_layer->val - 1)) / 2 + 1;
}
return num_ref;
}
@ -626,6 +633,7 @@ int msm_vidc_calculate_input_buffer_count(struct msm_vidc_inst *inst)
{
struct msm_vidc_format *fmt;
int extra_buff_count = 0;
struct v4l2_ctrl *max_layer = NULL;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
@ -655,6 +663,13 @@ int msm_vidc_calculate_input_buffer_count(struct msm_vidc_inst *inst)
extra_buff_count = msm_vidc_get_extra_buff_count(inst,
HAL_BUFFER_INPUT);
fmt->count_min = MIN_INPUT_BUFFERS;
if (is_hier_b_session(inst)) {
max_layer = get_ctrl(inst,
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
fmt->count_min = (1 << (max_layer->val - 1)) + 2;
}
fmt->count_min_host = fmt->count_actual =
fmt->count_min + extra_buff_count;

View file

@ -190,6 +190,25 @@ static inline bool is_internal_buffer(enum hal_buffer type)
return !!(buf_type & type);
}
static inline bool is_hier_b_session(struct msm_vidc_inst *inst)
{
struct v4l2_ctrl *max_layer = NULL;
struct v4l2_ctrl *frame_t = NULL;
if (inst->session_type == MSM_VIDC_ENCODER) {
max_layer = get_ctrl(inst,
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
frame_t = get_ctrl(inst,
V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE);
if (get_v4l2_codec(inst) == V4L2_PIX_FMT_HEVC &&
max_layer->val > 1 &&
frame_t->val ==
V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B)
return true;
}
return false;
}
static inline int msm_comm_g_ctrl(struct msm_vidc_inst *inst,
struct v4l2_control *ctrl)
{

View file

@ -541,6 +541,10 @@ struct hfi_intra_period {
u32 bframes;
};
struct hfi_adaptive_p_b_intra_period {
u32 nframes;
};
struct hfi_multi_stream {
u32 buffer_type;
u32 enable;