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 <asahukar@codeaurora.org>
This commit is contained in:
Akshata Sahukar
2021-03-11 13:21:21 -08:00
parent 5d45f82cbb
commit 98e799da29
8 changed files with 423 additions and 64 deletions

View File

@@ -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,

View File

@@ -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)

View File

@@ -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,

View File

@@ -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;

View File

@@ -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,

View File

@@ -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);

View File

@@ -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)

View File

@@ -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: