From 98e799da295c94468dfec00a4d236b195c9bd963 Mon Sep 17 00:00:00 2001 From: Akshata Sahukar Date: Thu, 11 Mar 2021 13:21:21 -0800 Subject: [PATCH] video: driver: Add support to handle GOP and its dependencies Add support to below mentioned properties: - HFI_PROP_LAYER_ENCODING_TYPE - HFI_PROP_LAYER_COUNT - HFI_PROP_MAX_GOP_FRAMES - HFI_PROP_MAX_B_FRAMES. Change-Id: I3be975a48dc668d0ec83f6ff13837488fc570b78 Signed-off-by: Akshata Sahukar --- driver/platform/waipio/src/msm_vidc_waipio.c | 64 ++-- .../variant/iris2/src/msm_vidc_buffer_iris2.c | 58 ++-- driver/vidc/inc/msm_vidc_control.h | 7 + driver/vidc/inc/msm_vidc_inst.h | 1 + driver/vidc/inc/msm_vidc_internal.h | 14 +- driver/vidc/src/msm_venc.c | 12 + driver/vidc/src/msm_vidc_control.c | 322 +++++++++++++++++- driver/vidc/src/msm_vidc_driver.c | 9 +- 8 files changed, 423 insertions(+), 64 deletions(-) diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index 417e83e404..8fd04dcd2e 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/driver/platform/waipio/src/msm_vidc_waipio.c @@ -60,6 +60,7 @@ static struct msm_platform_core_capability core_data_waipio[] = { {MAX_MBPS_HQ, 489600}, /* ((1920x1088)/256)@60fps */ {MAX_MBPF_B_FRAME, 32640}, /* 3840x2176/256 */ {MAX_MBPS_B_FRAME, 1958400}, /* 3840x2176/256 MBs@60fps */ + {MAX_ENH_LAYER_COUNT, 5}, {NUM_VPP_PIPE, 4}, {SW_PC, 1}, {SW_PC_DELAY, 20000}, /* 20000 ms (>HW_RESPONSE_TIMEOUT)*/ @@ -193,12 +194,6 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { {SCALE_X, DEC, H264|HEVC|VP9, 65536, 65536, 1, 65536}, {SCALE_Y, ENC, H264|HEVC, 8192, 65536, 1, 8192}, {SCALE_Y, DEC, H264|HEVC|VP9, 65536, 65536, 1, 65536}, - {B_FRAME, ENC, H264|HEVC, - V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE, - 1, V4L2_MPEG_MSM_VIDC_DISABLE, - V4L2_CID_MPEG_VIDEO_B_FRAMES, - HFI_PROP_MAX_B_FRAMES, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, {MB_CYCLES_VSP, ENC, CODECS_ALL, 25, 25, 1, 25}, {MB_CYCLES_VSP, DEC, CODECS_ALL, 25, 25, 1, 25}, @@ -328,7 +323,8 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { HFI_PROP_RATE_CONTROL, CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, {0}, - {LTR_COUNT, IR_RANDOM, TIME_DELTA_BASED_RC, I_FRAME_QP}, + {LTR_COUNT, IR_RANDOM, TIME_DELTA_BASED_RC, I_FRAME_QP, + ENH_LAYER_COUNT}, msm_vidc_adjust_bitrate_mode, msm_vidc_set_u32_enum}, {BITRATE_MODE, ENC, HEVC, @@ -343,7 +339,7 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, {0}, {LTR_COUNT, IR_RANDOM, TIME_DELTA_BASED_RC, - I_FRAME_QP, CONSTANT_QUALITY}, + I_FRAME_QP, CONSTANT_QUALITY, ENH_LAYER_COUNT}, msm_vidc_adjust_bitrate_mode, msm_vidc_set_u32_enum}, {LOSSLESS, ENC, HEVC|HEIC, @@ -375,14 +371,14 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { {BITRATE_MODE}, {0}, NULL, msm_vidc_set_constant_quality}, - // TODO: GOP dependencies {GOP_SIZE, ENC, CODECS_ALL, 0, INT_MAX, 1, 2 * DEFAULT_FPS - 1, V4L2_CID_MPEG_VIDEO_GOP_SIZE, HFI_PROP_MAX_GOP_FRAMES, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, - {0}, {0}, - NULL, msm_vidc_set_u32}, + CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, + {ENH_LAYER_COUNT}, + {0}, + msm_vidc_adjust_gop_size, msm_vidc_set_gop_size}, {GOP_CLOSURE, ENC, H264|HEVC, V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE, @@ -390,6 +386,15 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0}, + {B_FRAME, ENC, H264|HEVC, + 0, 7, 1, 0, + V4L2_CID_MPEG_VIDEO_B_FRAMES, + HFI_PROP_MAX_B_FRAMES, + CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, + {ENH_LAYER_COUNT}, + {0}, + msm_vidc_adjust_b_frame, msm_vidc_set_u32}, + {BLUR_TYPES, ENC, CODECS_ALL, VIDC_BLUR_NONE, VIDC_BLUR_ADAPTIVE, 1, VIDC_BLUR_NONE, V4L2_CID_MPEG_VIDC_VIDEO_BLUR_TYPES, @@ -662,8 +667,7 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { HFI_PROP_QP_PACKED, CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, - // TODO: Enable while reveiwing support for layer encoding - {HIER_CODING_TYPE, ENC, HEVC, + {LAYER_TYPE, ENC, HEVC, V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B, V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P, BIT(V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) | @@ -671,12 +675,9 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE, HFI_PROP_LAYER_ENCODING_TYPE, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, - {0}, {0}, - NULL, NULL}, + CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU}, - /* TODO(AS) - ctrl init failing. Need to fix - {HIER_CODING_TYPE, ENC, H264, + {LAYER_TYPE, ENC, H264, V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B, V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P, BIT(V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) | @@ -684,29 +685,32 @@ static struct msm_platform_inst_capability instance_data_waipio[] = { V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P, V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE, HFI_PROP_LAYER_ENCODING_TYPE, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU}, - */ + CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU}, - //TODO (AS) - {HIER_CODING, ENC, H264, + {LAYER_ENABLE, ENC, H264, V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE, 1, V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING, HFI_PROP_LAYER_ENCODING_TYPE, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + CAP_FLAG_OUTPUT_PORT}, - // TODO: add relationship with GOP_SIZE in caps - {HIER_CODING_LAYER, ENC, HEVC, + {ENH_LAYER_COUNT, ENC, HEVC, 0, 5, 1, 0, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER, HFI_PROP_LAYER_COUNT, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, + {BITRATE_MODE}, + {GOP_SIZE, B_FRAME}, + msm_vidc_adjust_layer_count, msm_vidc_set_layer_count_and_type}, - {HIER_CODING_LAYER, ENC, H264, - 0, 6, 1, 0, + {ENH_LAYER_COUNT, ENC, H264, + 0, 5, 1, 0, V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER, HFI_PROP_LAYER_COUNT, - CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, + CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, + {BITRATE_MODE}, + {GOP_SIZE, B_FRAME}, + msm_vidc_adjust_layer_count, msm_vidc_set_layer_count_and_type}, {L0_BR, ENC, HEVC, 1, 220000000, 1, 20000000, diff --git a/driver/variant/iris2/src/msm_vidc_buffer_iris2.c b/driver/variant/iris2/src/msm_vidc_buffer_iris2.c index 1841b7742e..8cf25feb12 100644 --- a/driver/variant/iris2/src/msm_vidc_buffer_iris2.c +++ b/driver/variant/iris2/src/msm_vidc_buffer_iris2.c @@ -277,13 +277,42 @@ static u32 msm_vidc_encoder_bin_size_iris2(struct msm_vidc_inst *inst) return size; } +static u32 msm_vidc_get_recon_buf_count(struct msm_vidc_inst *inst) +{ + u32 num_buf_recon = 0; + s32 n_bframe, ltr_count, hp_layers = 0, hb_layers = 0; + bool is_hybrid_hp = false; + u32 hfi_codec = 0; + + n_bframe = inst->capabilities->cap[B_FRAME].value; + ltr_count = inst->capabilities->cap[LTR_COUNT].value; + + if (inst->hfi_layer_type == HFI_HIER_B) { + hb_layers = inst->capabilities->cap[ENH_LAYER_COUNT].value + 1; + } else { + hp_layers = inst->capabilities->cap[ENH_LAYER_COUNT].value + 1; + if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR) + is_hybrid_hp = true; + } + + if (inst->codec == MSM_VIDC_H264) + hfi_codec = HFI_CODEC_ENCODE_AVC; + else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC) + hfi_codec = HFI_CODEC_ENCODE_HEVC; + + HFI_IRIS2_ENC_RECON_BUF_COUNT(num_buf_recon, n_bframe, ltr_count, + hp_layers, hb_layers, is_hybrid_hp, hfi_codec); + + return num_buf_recon; +} + static u32 msm_vidc_encoder_comv_size_iris2(struct msm_vidc_inst* inst) { u32 size = 0; u32 width, height, num_recon = 0; struct v4l2_format* f; - if (!inst || !inst->core) { + if (!inst || !inst->core || !inst->capabilities) { d_vpr_e("%s: invalid params\n", __func__); return size; } @@ -292,17 +321,11 @@ static u32 msm_vidc_encoder_comv_size_iris2(struct msm_vidc_inst* inst) width = f->fmt.pix_mp.width; height = f->fmt.pix_mp.height; - if (inst->codec == MSM_VIDC_H264) { - // TODO: replace zeros with appropriate variables - HFI_IRIS2_ENC_RECON_BUF_COUNT(num_recon, 0, 0, 0, 0, 0, - HFI_CODEC_ENCODE_AVC); + num_recon = msm_vidc_get_recon_buf_count(inst); + if (inst->codec == MSM_VIDC_H264) HFI_BUFFER_COMV_H264E(size, width, height, num_recon); - } else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC) { - // TODO: replace zeros with appropriate variables - HFI_IRIS2_ENC_RECON_BUF_COUNT(num_recon, 0, 0, 0, 0, 0, - HFI_CODEC_ENCODE_HEVC); + else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC) HFI_BUFFER_COMV_H265E(size, width, height, num_recon); - } i_vpr_l(inst, "%s: size %d\n", __func__, size); return size; @@ -521,23 +544,12 @@ int msm_buffer_size_iris2(struct msm_vidc_inst *inst, static int msm_buffer_encoder_dpb_count(struct msm_vidc_inst *inst) { - int count = 0; - - if (!inst) { + if (!inst || !inst->capabilities) { d_vpr_e("%s: invalid params\n", __func__); return 0; } - if (inst->codec == MSM_VIDC_H264) { - // TODO: replace zeros with appropriate variables - HFI_IRIS2_ENC_RECON_BUF_COUNT(count, 0, 0, 0, 0, 0, - HFI_CODEC_ENCODE_AVC); - } else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC) { - // TODO: replace zeros with appropriate variables - HFI_IRIS2_ENC_RECON_BUF_COUNT(count, 0, 0, 0, 0, 0, - HFI_CODEC_ENCODE_HEVC); - } - return count; + return msm_vidc_get_recon_buf_count(inst); } static int msm_buffer_decoder_dpb_count(struct msm_vidc_inst *inst) diff --git a/driver/vidc/inc/msm_vidc_control.h b/driver/vidc/inc/msm_vidc_control.h index 0d7fd8a574..125aee6111 100644 --- a/driver/vidc/inc/msm_vidc_control.h +++ b/driver/vidc/inc/msm_vidc_control.h @@ -28,6 +28,9 @@ int msm_vidc_adjust_mark_ltr(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_ir_random(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_delta_based_rc(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_layer_count(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_gop_size(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_b_frame(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_hevc_min_qp(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_hevc_max_qp(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_hevc_frame_qp(void *instance, struct v4l2_ctrl *ctrl); @@ -49,6 +52,10 @@ int msm_vidc_set_chroma_qp_index_offset(void *instance, enum msm_vidc_inst_capability_type cap_id); int msm_vidc_set_slice_count(void* instance, enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_layer_count_and_type(void *instance, + enum msm_vidc_inst_capability_type cap_id); +int msm_vidc_set_gop_size(void *instance, + enum msm_vidc_inst_capability_type cap_id); int msm_vidc_set_u32(void *instance, enum msm_vidc_inst_capability_type cap_id); int msm_vidc_set_u32_enum(void *instance, diff --git a/driver/vidc/inc/msm_vidc_inst.h b/driver/vidc/inc/msm_vidc_inst.h index 4b8459a6fa..0b2a9e3bf4 100644 --- a/driver/vidc/inc/msm_vidc_inst.h +++ b/driver/vidc/inc/msm_vidc_inst.h @@ -103,6 +103,7 @@ struct msm_vidc_inst { struct msm_vidc_inst_cap_entry children; struct msm_vidc_inst_cap_entry firmware; enum hfi_rate_control hfi_rc_type; + enum hfi_layer_encoding_type hfi_layer_type; bool request; struct vb2_queue vb2q[MAX_PORT]; struct msm_vidc_rectangle crop; diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index 5f5d6c44b4..8cdc6e64ef 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -50,6 +50,11 @@ #define BIT_DEPTH_10 (10 << 16 | 10) #define CODED_FRAMES_PROGRESSIVE 0x0 #define CODED_FRAMES_INTERLACE 0x1 +/* TODO: move below macros to waipio.c */ +#define MAX_ENH_LAYER_HB 3 +#define MAX_HEVC_ENH_LAYER_SLIDING_WINDOW 5 +#define MAX_AVC_ENH_LAYER_SLIDING_WINDOW 3 +#define MAX_AVC_ENH_LAYER_HYBRID_HP 5 /* TODO * #define MAX_SUPERFRAME_COUNT 32 @@ -269,6 +274,7 @@ enum msm_vidc_core_capability_type { MAX_MBPS_HQ, MAX_MBPF_B_FRAME, MAX_MBPS_B_FRAME, + MAX_ENH_LAYER_COUNT, NUM_VPP_PIPE, SW_PC, SW_PC_DELAY, @@ -313,7 +319,6 @@ enum msm_vidc_inst_capability_type { OPERATING_RATE, SCALE_X, SCALE_Y, - B_FRAME, MB_CYCLES_VSP, MB_CYCLES_VPP, MB_CYCLES_LP, @@ -339,6 +344,7 @@ enum msm_vidc_inst_capability_type { CONSTANT_QUALITY, GOP_SIZE, GOP_CLOSURE, + B_FRAME, BLUR_TYPES, BLUR_RESOLUTION, CSC, @@ -374,9 +380,9 @@ enum msm_vidc_inst_capability_type { L4_QP, L5_QP, HIER_LAYER_QP, - HIER_CODING_TYPE, - HIER_CODING, - HIER_CODING_LAYER, + LAYER_TYPE, + LAYER_ENABLE, + ENH_LAYER_COUNT, L0_BR, L1_BR, L2_BR, diff --git a/driver/vidc/src/msm_venc.c b/driver/vidc/src/msm_venc.c index 563e81c311..cd3c8e27d5 100644 --- a/driver/vidc/src/msm_venc.c +++ b/driver/vidc/src/msm_venc.c @@ -986,12 +986,23 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd) int msm_venc_streamoff_output(struct msm_vidc_inst *inst) { int rc = 0; + struct msm_vidc_core *core; if (!inst || !inst->core || !inst->capabilities) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } + core = inst->core; + if (!core->capabilities) { + i_vpr_e(inst, "%s: core capabilities is NULL\n", __func__); + return -EINVAL; + } + + /* restore LAYER_COUNT max allowed value */ + inst->capabilities->cap[ENH_LAYER_COUNT].max = + core->capabilities[MAX_ENH_LAYER_COUNT].value; + rc = msm_vidc_session_streamoff(inst, OUTPUT_PORT); if (rc) return rc; @@ -1774,6 +1785,7 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) inst->buffers.input_meta.size = 0; inst->hfi_rc_type = HFI_RC_VBR_CFR; + inst->hfi_layer_type = HFI_HIER_P_SLIDING_WINDOW; rc = msm_venc_codec_change(inst, inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat); diff --git a/driver/vidc/src/msm_vidc_control.c b/driver/vidc/src/msm_vidc_control.c index 5b32defb72..4c6505c662 100644 --- a/driver/vidc/src/msm_vidc_control.c +++ b/driver/vidc/src/msm_vidc_control.c @@ -18,6 +18,8 @@ static bool is_priv_ctrl(u32 id) { + bool private = false; + if (IS_PRIV_CTRL(id)) return true; @@ -25,8 +27,21 @@ static bool is_priv_ctrl(u32 id) * Treat below standard controls as private because * we have added custom values to the controls */ + switch (id) { + /* + * TODO: V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE is + * std ctrl. But needs some fixes in v4l2-ctrls.c. Hence, + * make this as private ctrl for time being + */ + case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: + private = true; + break; + default: + private = false; + break; + } - return false; + return private; } static bool is_meta_ctrl(u32 id) @@ -75,6 +90,12 @@ static const char *const mpeg_video_blur_types[] = { NULL, }; +static const char *const mpeg_video_avc_coding_layer[] = { + "B", + "P", + NULL, +}; + static const char *const roi_map_type[] = { "None", "2-bit", @@ -112,6 +133,8 @@ static const char * const * msm_vidc_get_qmenu_type( return mpeg_video_stream_format; case V4L2_CID_MPEG_VIDC_VIDEO_BLUR_TYPES: return mpeg_video_blur_types; + case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: + return mpeg_video_avc_coding_layer; default: i_vpr_e(inst, "%s: No available qmenu for ctrl %#x\n", __func__, control_id); @@ -257,10 +280,17 @@ static int msm_vidc_get_parent_value(struct msm_vidc_inst* inst, int rc = 0; if (is_parent_available(inst, cap, parent)) { - if (parent == BITRATE_MODE) + switch (parent) { + case BITRATE_MODE: *value = inst->hfi_rc_type; - else + break; + case LAYER_TYPE: + *value = inst->hfi_layer_type; + break; + default: *value = inst->capabilities->cap[parent].value; + break; + } } else { i_vpr_e(inst, "%s: missing parent %d for cap %d, please correct database\n", @@ -994,6 +1024,219 @@ int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl) return 0; } +static int msm_vidc_adjust_static_layer_count_and_type(struct msm_vidc_inst *inst, + s32 layer_count) +{ + bool hb_requested = false; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (!layer_count) { + i_vpr_h(inst, "client not enabled layer encoding\n"); + goto exit; + } + + if (inst->hfi_rc_type == HFI_RC_CQ) { + i_vpr_h(inst, "rc type is CQ, disabling layer encoding\n"); + layer_count = 0; + goto exit; + } + + if (inst->codec == MSM_VIDC_H264) { + if (!inst->capabilities->cap[LAYER_ENABLE].value) { + layer_count = 0; + goto exit; + } + + hb_requested = (inst->capabilities->cap[LAYER_TYPE].value == + V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) ? + true : false; + } else if (inst->codec == MSM_VIDC_HEVC) { + hb_requested = (inst->capabilities->cap[LAYER_TYPE].value == + V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) ? + true : false; + } + + if (hb_requested && inst->hfi_rc_type != HFI_RC_VBR_CFR) { + i_vpr_h(inst, + "%s: HB layer encoding is supported for VBR rc only\n", + __func__); + layer_count = 0; + goto exit; + } + + /* decide hfi layer type */ + if (hb_requested) { + inst->hfi_layer_type = HFI_HIER_B; + } else { + /* HP requested */ + inst->hfi_layer_type = HFI_HIER_P_SLIDING_WINDOW; + if (inst->codec == MSM_VIDC_H264 && + inst->hfi_rc_type == HFI_RC_VBR_CFR) + inst->hfi_layer_type = HFI_HIER_P_HYBRID_LTR; + } + + /* sanitize layer count based on layer type and codec */ + if (inst->hfi_layer_type == HFI_HIER_B) { + if (layer_count > MAX_ENH_LAYER_HB) + layer_count = MAX_ENH_LAYER_HB; + } else if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR) { + if (layer_count > MAX_AVC_ENH_LAYER_HYBRID_HP) + layer_count = MAX_AVC_ENH_LAYER_HYBRID_HP; + } else if (inst->hfi_layer_type == HFI_HIER_P_SLIDING_WINDOW) { + if (inst->codec == MSM_VIDC_H264) { + if (layer_count > MAX_AVC_ENH_LAYER_SLIDING_WINDOW) + layer_count = MAX_AVC_ENH_LAYER_SLIDING_WINDOW; + } else { + if (layer_count > MAX_HEVC_ENH_LAYER_SLIDING_WINDOW) + layer_count = MAX_HEVC_ENH_LAYER_SLIDING_WINDOW; + } + } + +exit: + msm_vidc_update_cap_value(inst, ENH_LAYER_COUNT, + layer_count, __func__); + inst->capabilities->cap[ENH_LAYER_COUNT].max = layer_count; + return 0; +} + +int msm_vidc_adjust_layer_count(void *instance, struct v4l2_ctrl *ctrl) +{ + int rc = 0; + struct msm_vidc_inst_capability *capability; + s32 client_layer_count; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + client_layer_count = ctrl ? ctrl->val : + capability->cap[ENH_LAYER_COUNT].value; + + if (!is_parent_available(inst, ENH_LAYER_COUNT, BITRATE_MODE)) { + i_vpr_e(inst, "%s: missing parent %d in database", + __func__, BITRATE_MODE); + return -EINVAL; + } + + if (!inst->vb2q[OUTPUT_PORT].streaming) { + rc = msm_vidc_adjust_static_layer_count_and_type(inst, + client_layer_count); + if (rc) + goto exit; + } else { + if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR || + inst->hfi_layer_type == HFI_HIER_P_SLIDING_WINDOW) { + /* dynamic layer count change is only supported for HP */ + if (client_layer_count > + inst->capabilities->cap[ENH_LAYER_COUNT].max) + client_layer_count = + inst->capabilities->cap[ENH_LAYER_COUNT].max; + + msm_vidc_update_cap_value(inst, ENH_LAYER_COUNT, + client_layer_count, __func__); + } + } + +exit: + return rc; +} + +/* + * 1. GOP calibration is only done for HP layer encoding type. + * 2. Dynamic GOP size should not exceed static GOP size + * 3. For HB case, or when layer encoding is not enabled, + * client set GOP size is directly set to FW. + */ +int msm_vidc_adjust_gop_size(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + s32 adjusted_value, enh_layer_count = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : capability->cap[GOP_SIZE].value; + + if (msm_vidc_get_parent_value(inst, GOP_SIZE, + ENH_LAYER_COUNT, &enh_layer_count, __func__)) + return -EINVAL; + + if (!enh_layer_count) + goto exit; + + /* calibrate GOP size */ + if (inst->hfi_layer_type == HFI_HIER_P_SLIDING_WINDOW || + inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR) { + /* + * Layer encoding needs GOP size to be multiple of subgop size + * And subgop size is 2 ^ number of enhancement layers. + */ + u32 min_gop_size; + u32 num_subgops; + + /* v4l2 layer count is the number of enhancement layers */ + min_gop_size = 1 << enh_layer_count; + num_subgops = (adjusted_value + (min_gop_size >> 1)) / + min_gop_size; + if (num_subgops) + adjusted_value = num_subgops * min_gop_size; + else + adjusted_value = min_gop_size; + } + +exit: + msm_vidc_update_cap_value(inst, GOP_SIZE, adjusted_value, __func__); + return 0; +} + +int msm_vidc_adjust_b_frame(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + s32 adjusted_value, enh_layer_count = -1; + const u32 max_bframe_size = 7; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + if (inst->vb2q[OUTPUT_PORT].streaming) + return 0; + + adjusted_value = ctrl ? ctrl->val : capability->cap[B_FRAME].value; + + if (msm_vidc_get_parent_value(inst, B_FRAME, + ENH_LAYER_COUNT, &enh_layer_count, __func__)) + return -EINVAL; + + if (!enh_layer_count || inst->hfi_layer_type != HFI_HIER_B) { + adjusted_value = 0; + goto exit; + } + + adjusted_value = (2 << enh_layer_count) - 1; + /* Allowed Bframe values are 0, 1, 3, 7 */ + if (adjusted_value > max_bframe_size) + adjusted_value = max_bframe_size; + +exit: + msm_vidc_update_cap_value(inst, B_FRAME, adjusted_value, __func__); + return 0; +} + int msm_vidc_adjust_hevc_min_qp(void *instance, struct v4l2_ctrl *ctrl) { int rc = 0; @@ -1493,6 +1736,79 @@ int msm_vidc_set_nal_length(void* instance, return rc; } +int msm_vidc_set_layer_count_and_type(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + u32 hfi_layer_count, hfi_layer_type = 0; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (!inst->vb2q[OUTPUT_PORT].streaming) { + /* set layer type */ + hfi_layer_type = inst->hfi_layer_type; + cap_id = LAYER_TYPE; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM, + &hfi_layer_type, sizeof(u32), __func__); + if (rc) + goto exit; + } else { + if (inst->hfi_layer_type == HFI_HIER_B) { + i_vpr_l(inst, + "%s: HB dyn layers change is not supported\n", + __func__); + return 0; + } + } + + /* set layer count */ + cap_id = ENH_LAYER_COUNT; + /* hfi baselayer starts from 1 */ + hfi_layer_count = inst->capabilities->cap[ENH_LAYER_COUNT].value + 1; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_layer_count, sizeof(u32), __func__); + if (rc) + goto exit; + +exit: + return rc; +} + +int msm_vidc_set_gop_size(void *instance, + enum msm_vidc_inst_capability_type cap_id) +{ + int rc = 0; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; + u32 hfi_value; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (inst->vb2q[OUTPUT_PORT].streaming) { + if (inst->hfi_layer_type == HFI_HIER_B) { + i_vpr_l(inst, + "%s: HB dyn GOP setting is not supported\n", + __func__); + return 0; + } + } + + hfi_value = inst->capabilities->cap[GOP_SIZE].value; + + rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32, + &hfi_value, sizeof(u32), __func__); + + return rc; +} + /* TODO int msm_vidc_set_flip(void *instance, enum msm_vidc_inst_capability_type cap_id) diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index cfc670482d..c99ef91f91 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -62,7 +62,6 @@ static const struct msm_vidc_cap_name cap_name_arr[] = { {OPERATING_RATE, "OPERATING_RATE" }, {SCALE_X, "SCALE_X" }, {SCALE_Y, "SCALE_Y" }, - {B_FRAME, "B_FRAME" }, {MB_CYCLES_VSP, "MB_CYCLES_VSP" }, {MB_CYCLES_VPP, "MB_CYCLES_VPP" }, {MB_CYCLES_LP, "MB_CYCLES_LP" }, @@ -88,6 +87,7 @@ static const struct msm_vidc_cap_name cap_name_arr[] = { {CONSTANT_QUALITY, "CONSTANT_QUALITY" }, {GOP_SIZE, "GOP_SIZE" }, {GOP_CLOSURE, "GOP_CLOSURE" }, + {B_FRAME, "B_FRAME" }, {BLUR_TYPES, "BLUR_TYPES" }, {BLUR_RESOLUTION, "BLUR_RESOLUTION" }, {CSC, "CSC" }, @@ -123,9 +123,9 @@ static const struct msm_vidc_cap_name cap_name_arr[] = { {L4_QP, "L4_QP" }, {L5_QP, "L5_QP" }, {HIER_LAYER_QP, "HIER_LAYER_QP" }, - {HIER_CODING_TYPE, "HIER_CODING_TYPE" }, - {HIER_CODING, "HIER_CODING" }, - {HIER_CODING_LAYER, "HIER_CODING_LAYER" }, + {LAYER_TYPE, "LAYER_TYPE" }, + {LAYER_ENABLE, "LAYER_ENABLE" }, + {ENH_LAYER_COUNT, "ENH_LAYER_COUNT" }, {L0_BR, "L0_BR" }, {L1_BR, "L1_BR" }, {L2_BR, "L2_BR" }, @@ -1063,6 +1063,7 @@ bool msm_vidc_allow_s_ctrl(struct msm_vidc_inst *inst, u32 id) case V4L2_CID_VFLIP: case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER: + case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER: case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR: case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR: case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR: