mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 06:09:23 -04:00
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:
parent
d80c41100d
commit
911dc56174
5 changed files with 194 additions and 44 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue