Loading drivers/media/platform/msm/vidc/msm_vdec.c +9 −95 Original line number Diff line number Diff line Loading @@ -13,16 +13,13 @@ #include "vidc_hfi_api.h" #include "msm_vidc_debug.h" #include "msm_vidc_clocks.h" #include "msm_vidc_buffer_calculations.h" #define MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS MIN_NUM_OUTPUT_BUFFERS #define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS MIN_NUM_CAPTURE_BUFFERS #define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9 8 #define MIN_NUM_DEC_OUTPUT_BUFFERS 4 #define MIN_NUM_DEC_CAPTURE_BUFFERS 4 /* Y=16(0-9bits), Cb(10-19bits)=Cr(20-29bits)=128, black by default */ #define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8020010 #define MAX_VP9D_INST_COUNT 6 #define MAX_4K_MBPF 38736 /* (4096 * 2304 / 256) */ static const char *const vp8_profile_level[] = { "Unused", Loading Loading @@ -454,61 +451,6 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = { #define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls) static u32 get_dec_input_frame_size(struct msm_vidc_inst *inst) { u32 frame_size, num_mbs; u32 div_factor = 1; u32 base_res_mbs = MAX_4K_MBPF; u32 width = inst->prop.width[OUTPUT_PORT]; u32 height = inst->prop.height[OUTPUT_PORT]; /* * Decoder input size calculation: * If clip is 8k buffer size is calculated for 8k : 8k mbs/4 * For 8k cases we expect width/height to be set always. * In all other cases size is calculated for 4k: * 4k mbs for VP8/VP9 and 4k/2 for remaining codecs */ num_mbs = ((width + 15) >> 4) * ((height + 15) >> 4); if (num_mbs > MAX_4K_MBPF) { div_factor = 4; base_res_mbs = inst->capability.mbs_per_frame.max; } else { base_res_mbs = MAX_4K_MBPF; if (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) div_factor = 1; else div_factor = 2; } frame_size = base_res_mbs * 3 / 2 / div_factor; /* multiply by 10/8 (1.25) to get size for 10 bit case */ if ((inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) || (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_HEVC)) frame_size = frame_size + (frame_size >> 2); if (inst->buffer_size_limit && (inst->buffer_size_limit < frame_size)) { frame_size = inst->buffer_size_limit; dprintk(VIDC_DBG, "input buffer size limited to %d\n", frame_size); } else { dprintk(VIDC_DBG, "set input buffer size to %d\n", frame_size); } return ALIGN(frame_size, SZ_4K); } static u32 get_dec_output_frame_size(struct msm_vidc_inst *inst) { u32 hfi_fmt; hfi_fmt = msm_comm_convert_color_fmt(inst->fmts[CAPTURE_PORT].fourcc); return VENUS_BUFFER_SIZE(hfi_fmt, inst->prop.width[CAPTURE_PORT], inst->prop.height[CAPTURE_PORT]); } struct msm_vidc_format vdec_formats[] = { { .name = "YCbCr Semiplanar 4:2:0", Loading Loading @@ -701,7 +643,7 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) } f->fmt.pix_mp.plane_fmt[0].sizeimage = get_dec_output_frame_size(inst); msm_vidc_calculate_dec_output_frame_size(inst); extra_idx = EXTRADATA_IDX(inst->bufq[fmt->type].num_planes); if (extra_idx && extra_idx < VIDEO_MAX_PLANES) { Loading Loading @@ -770,7 +712,7 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) goto err_invalid_fmt; } max_input_size = get_dec_input_frame_size(inst); max_input_size = msm_vidc_calculate_dec_input_frame_size(inst); if (f->fmt.pix_mp.plane_fmt[0].sizeimage > max_input_size || !f->fmt.pix_mp.plane_fmt[0].sizeimage) { f->fmt.pix_mp.plane_fmt[0].sizeimage = max_input_size; Loading Loading @@ -845,9 +787,8 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) inst->bufq[OUTPUT_PORT].num_planes = 1; inst->bufq[CAPTURE_PORT].num_planes = 2; inst->bufq[CAPTURE_PORT].plane_sizes[1] = VENUS_EXTRADATA_SIZE( inst->prop.height[CAPTURE_PORT], inst->prop.width[CAPTURE_PORT]); msm_vidc_calculate_dec_output_extra_size(inst); inst->clk_data.frame_rate = (DEFAULT_FPS << 16); inst->clk_data.operating_rate = (DEFAULT_FPS << 16); if (core->resources.decode_batching) Loading Loading @@ -907,7 +848,6 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) { int rc = 0; struct hal_buffer_requirements *bufreq; if (!inst || !inst->core || !inst->core->device) { dprintk(VIDC_ERR, "%s invalid parameters\n", __func__); Loading Loading @@ -950,36 +890,10 @@ int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) inst->flags |= VIDC_THUMBNAIL; msm_dcvs_try_enable(inst); bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT); if (!bufreq) return -EINVAL; bufreq->buffer_count_min = MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS; bufreq->buffer_count_min_host = MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS; bufreq->buffer_count_actual = MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS; bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT); if (!bufreq) return -EINVAL; /* VP9 super frame requires multiple frames decoding */ if (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) { bufreq->buffer_count_min = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9; bufreq->buffer_count_min_host = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9; bufreq->buffer_count_actual = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9; } else { bufreq->buffer_count_min = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS; bufreq->buffer_count_min_host = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS; bufreq->buffer_count_actual = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS; rc = msm_vidc_set_buffer_count_for_thumbnail(inst); if (rc) { dprintk(VIDC_ERR, "Failed to set buffer count\n"); return rc; } break; case V4L2_CID_MPEG_VIDC_VIDEO_SECURE: Loading drivers/media/platform/msm/vidc/msm_venc.c +12 −115 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #include "vidc_hfi_api.h" #include "msm_vidc_debug.h" #include "msm_vidc_clocks.h" #include "msm_vidc_buffer_calculations.h" #define MIN_BIT_RATE 32000 #define MAX_BIT_RATE 1200000000 Loading @@ -18,9 +19,7 @@ #define BIT_RATE_STEP 1 #define MAX_SLICE_BYTE_SIZE ((MAX_BIT_RATE)>>3) #define MIN_SLICE_BYTE_SIZE 512 #define NUM_MBS_720P (((1280 + 15) >> 4) * ((720 + 15) >> 4)) #define NUM_MBS_4k (((4096 + 15) >> 4) * ((2304 + 15) >> 4)) #define MAX_SLICE_MB_SIZE NUM_MBS_4k #define MAX_SLICE_MB_SIZE (((4096 + 15) >> 4) * ((2304 + 15) >> 4)) #define QP_ENABLE_I 0x1 #define QP_ENABLE_P 0x2 #define QP_ENABLE_B 0x4 Loading Loading @@ -943,110 +942,6 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = { #define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls) static u32 get_enc_input_frame_size(struct msm_vidc_inst *inst) { u32 hfi_fmt; hfi_fmt = msm_comm_convert_color_fmt(inst->fmts[OUTPUT_PORT].fourcc); return VENUS_BUFFER_SIZE(hfi_fmt, inst->prop.width[OUTPUT_PORT], inst->prop.height[OUTPUT_PORT]); } static u32 get_enc_output_frame_size(struct msm_vidc_inst *inst) { u32 frame_size; u32 mbs_per_frame; u32 width, height; /* * Encoder output size calculation: * For resolution < 720p : YUVsize * 4 * For resolution > 720p & <= 4K : YUVsize / 2 * For resolution > 4k : YUVsize / 4 */ width = inst->prop.width[CAPTURE_PORT]; height = inst->prop.height[CAPTURE_PORT]; mbs_per_frame = ((width + 15) >> 4) * ((height + 15) >> 4); frame_size = (width * height * 3) >> 1; if (mbs_per_frame < NUM_MBS_720P) frame_size = frame_size << 2; else if (mbs_per_frame <= NUM_MBS_4k) frame_size = frame_size >> 1; else frame_size = frame_size >> 2; if ((inst->rc_type == RATE_CONTROL_OFF) || (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)) frame_size = frame_size << 1; return ALIGN(frame_size, SZ_4K); } static inline u32 ROI_EXTRADATA_SIZE( u32 width, u32 height, u32 lcu_size) { u32 lcu_width = 0; u32 lcu_height = 0; u32 n_shift = 0; while (lcu_size && !(lcu_size & 0x1)) { n_shift++; lcu_size = lcu_size >> 1; } lcu_width = (width + (lcu_size - 1)) >> n_shift; lcu_height = (height + (lcu_size - 1)) >> n_shift; return (((lcu_width + 7) >> 3) << 3) * lcu_height * 2; } static u32 get_enc_input_extra_size(struct msm_vidc_inst *inst, u32 extra_types) { u32 size = 0; u32 width = inst->prop.width[OUTPUT_PORT]; u32 height = inst->prop.height[OUTPUT_PORT]; u32 extradata_count = 0; /* Add size for default extradata */ size += sizeof(struct msm_vidc_enc_cvp_metadata_payload); extradata_count++; if (extra_types & EXTRADATA_ENC_INPUT_ROI) { u32 lcu_size = 16; if (inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_HEVC) lcu_size = 32; size += ROI_EXTRADATA_SIZE(width, height, lcu_size); extradata_count++; } if (extra_types & EXTRADATA_ENC_INPUT_HDR10PLUS) { size += sizeof(struct hfi_hdr10_pq_sei); extradata_count++; } /* Add extradata header sizes including EXTRADATA_NONE */ if (size) size += sizeof(struct msm_vidc_extradata_header) * (extradata_count + 1); return ALIGN(size, SZ_4K); } static u32 get_enc_output_extra_size(struct msm_vidc_inst *inst, u32 extra_types) { u32 size = 0; if (extra_types & EXTRADATA_ADVANCED) size += sizeof(struct msm_vidc_metadata_ltr_payload); /* Add size for extradata none */ if (size) size += sizeof(struct msm_vidc_extradata_header); return ALIGN(size, SZ_4K); } static struct msm_vidc_format venc_formats[] = { { .name = "YCbCr Semiplanar 4:2:0", Loading Loading @@ -1211,7 +1106,7 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) } buff_req_buffer->buffer_size = get_enc_input_extra_size(inst, EXTRADATA_DEFAULT); msm_vidc_calculate_enc_input_extra_size(inst); inst->bufq[OUTPUT_PORT].plane_sizes[1] = buff_req_buffer->buffer_size; Loading Loading @@ -1368,9 +1263,10 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) * update bitstream buffer size based on width & height * updating extradata buffer size is not required as * it is already updated when extradata control is set * and it is not dependent on frame size */ inst->bufq[fmt->type].plane_sizes[0] = get_enc_output_frame_size(inst); msm_vidc_calculate_enc_output_frame_size(inst); f->fmt.pix_mp.num_planes = inst->bufq[fmt->type].num_planes; for (i = 0; i < inst->bufq[fmt->type].num_planes; i++) { Loading Loading @@ -1403,11 +1299,13 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) /* * update bitstream buffer size based on width & height * updating extradata buffer size is not required as * it is already updated when extradata control is set * update extradata buffer size as it may change due to * frame size change. */ inst->bufq[fmt->type].plane_sizes[0] = get_enc_input_frame_size(inst); msm_vidc_calculate_enc_input_frame_size(inst); inst->bufq[fmt->type].plane_sizes[1] = msm_vidc_calculate_enc_input_extra_size(inst); f->fmt.pix_mp.num_planes = inst->bufq[fmt->type].num_planes; for (i = 0; i < inst->bufq[fmt->type].num_planes; i++) { f->fmt.pix_mp.plane_fmt[i].sizeimage = Loading Loading @@ -1678,8 +1576,7 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) } buff_req_buffer->buffer_size = get_enc_input_extra_size(inst, ctrl->val); msm_vidc_calculate_enc_input_extra_size(inst); inst->bufq[OUTPUT_PORT].plane_sizes[1] = buff_req_buffer->buffer_size; } Loading @@ -1697,7 +1594,7 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) } buff_req_buffer->buffer_size = get_enc_output_extra_size(inst, ctrl->val); msm_vidc_calculate_enc_output_extra_size(inst); inst->bufq[CAPTURE_PORT].plane_sizes[1] = buff_req_buffer->buffer_size; } Loading drivers/media/platform/msm/vidc/msm_vidc_buffer_calculations.c +335 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,17 @@ #include "msm_vidc_debug.h" #include "msm_vidc_common.h" #include "msm_vidc_buffer_calculations.h" #define MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS MIN_NUM_OUTPUT_BUFFERS #define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS MIN_NUM_CAPTURE_BUFFERS #define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9 8 /* extra o/p buffers in case of encoder dcvs */ #define DCVS_ENC_EXTRA_INPUT_BUFFERS 4 /* extra o/p buffers in case of decoder dcvs */ #define DCVS_DEC_EXTRA_OUTPUT_BUFFERS 4 #define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_WIDTH 32 #define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_HEIGHT 8 Loading Loading @@ -239,6 +250,8 @@ #define HFI_VENUS_HEIGHT_ALIGNMENT 32 #define SYSTEM_LAL_TILE10 192 #define NUM_MBS_720P (((1280 + 15) >> 4) * ((720 + 15) >> 4)) #define NUM_MBS_4k (((4096 + 15) >> 4) * ((2304 + 15) >> 4)) static inline u32 calculate_h264d_scratch_size(struct msm_vidc_inst *inst, u32 width, u32 height, bool is_interlaced); Loading Loading @@ -577,6 +590,328 @@ void msm_vidc_init_buffer_size_calculators(struct msm_vidc_inst *inst) msm_vidc_calculate_internal_buffer_sizes; } int msm_vidc_init_buffer_count(struct msm_vidc_inst *inst) { int extra_buff_count = 0; struct hal_buffer_requirements *bufreq; int port; if (!is_decode_session(inst) && !is_encode_session(inst)) return 0; if (is_decode_session(inst)) port = OUTPUT_PORT; else port = CAPTURE_PORT; /* Update input buff counts */ bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT); if (!bufreq) return -EINVAL; extra_buff_count = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_INPUT); bufreq->buffer_count_min = inst->fmts[port].input_min_count; /* batching needs minimum batch size count of input buffers */ if (inst->core->resources.decode_batching && is_decode_session(inst) && bufreq->buffer_count_min < inst->batch.size) bufreq->buffer_count_min = inst->batch.size; bufreq->buffer_count_min_host = bufreq->buffer_count_actual = bufreq->buffer_count_min + extra_buff_count; dprintk(VIDC_DBG, "%s: %x : input min %d min_host %d actual %d\n", __func__, hash32_ptr(inst->session), bufreq->buffer_count_min, bufreq->buffer_count_min_host, bufreq->buffer_count_actual); bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT); if (!bufreq) return -EINVAL; bufreq->buffer_count_min = inst->fmts[port].input_min_count; bufreq->buffer_count_min_host = bufreq->buffer_count_actual = bufreq->buffer_count_min + extra_buff_count; /* Update output buff count */ bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT); if (!bufreq) return -EINVAL; extra_buff_count = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_OUTPUT); bufreq->buffer_count_min = inst->fmts[port].output_min_count; bufreq->buffer_count_min_host = bufreq->buffer_count_actual = bufreq->buffer_count_min + extra_buff_count; dprintk(VIDC_DBG, "%s: %x : output min %d min_host %d actual %d\n", __func__, hash32_ptr(inst->session), bufreq->buffer_count_min, bufreq->buffer_count_min_host, bufreq->buffer_count_actual); bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_OUTPUT); if (!bufreq) return -EINVAL; bufreq->buffer_count_min = inst->fmts[port].output_min_count; bufreq->buffer_count_min_host = bufreq->buffer_count_actual = bufreq->buffer_count_min + extra_buff_count; return 0; } u32 msm_vidc_set_buffer_count_for_thumbnail(struct msm_vidc_inst *inst) { struct hal_buffer_requirements *bufreq; bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT); if (!bufreq) return -EINVAL; bufreq->buffer_count_min = MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS; bufreq->buffer_count_min_host = MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS; bufreq->buffer_count_actual = MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS; bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT); if (!bufreq) return -EINVAL; /* VP9 super frame requires multiple frames decoding */ if (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) { bufreq->buffer_count_min = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9; bufreq->buffer_count_min_host = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9; bufreq->buffer_count_actual = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9; } else { bufreq->buffer_count_min = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS; bufreq->buffer_count_min_host = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS; bufreq->buffer_count_actual = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS; } return 0; } int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst, enum hal_buffer buffer_type) { unsigned int count = 0; if (!inst || !inst->core) { dprintk(VIDC_ERR, "%s Invalid args\n", __func__); return 0; } /* * no extra buffers for thumbnail session because * neither dcvs nor batching will be enabled */ if (is_thumbnail_session(inst)) return 0; /* Add DCVS extra buffer count */ if (inst->core->resources.dcvs) { if (is_decode_session(inst) && buffer_type == HAL_BUFFER_OUTPUT) { count += DCVS_DEC_EXTRA_OUTPUT_BUFFERS; } else if ((is_encode_session(inst) && buffer_type == HAL_BUFFER_INPUT)) { count += DCVS_ENC_EXTRA_INPUT_BUFFERS; } } /* * if platform supports decode batching ensure minimum * batch size count of extra buffers added on output port */ if (buffer_type == HAL_BUFFER_OUTPUT) { if (inst->core->resources.decode_batching && is_decode_session(inst) && count < inst->batch.size) count = inst->batch.size; } return count; } u32 msm_vidc_calculate_dec_input_frame_size(struct msm_vidc_inst *inst) { u32 frame_size, num_mbs; u32 div_factor = 1; u32 base_res_mbs = NUM_MBS_4k; u32 width = inst->prop.width[OUTPUT_PORT]; u32 height = inst->prop.height[OUTPUT_PORT]; /* * Decoder input size calculation: * If clip is 8k buffer size is calculated for 8k : 8k mbs/4 * For 8k cases we expect width/height to be set always. * In all other cases size is calculated for 4k: * 4k mbs for VP8/VP9 and 4k/2 for remaining codecs */ num_mbs = ((width + 15) >> 4) * ((height + 15) >> 4); if (num_mbs > NUM_MBS_4k) { div_factor = 4; base_res_mbs = inst->capability.mbs_per_frame.max; } else { base_res_mbs = NUM_MBS_4k; if (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) div_factor = 1; else div_factor = 2; } frame_size = base_res_mbs * 3 / 2 / div_factor; /* multiply by 10/8 (1.25) to get size for 10 bit case */ if ((inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) || (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_HEVC)) frame_size = frame_size + (frame_size >> 2); if (inst->buffer_size_limit && (inst->buffer_size_limit < frame_size)) { frame_size = inst->buffer_size_limit; dprintk(VIDC_DBG, "input buffer size limited to %d\n", frame_size); } else { dprintk(VIDC_DBG, "set input buffer size to %d\n", frame_size); } return ALIGN(frame_size, SZ_4K); } u32 msm_vidc_calculate_dec_output_frame_size(struct msm_vidc_inst *inst) { u32 hfi_fmt; hfi_fmt = msm_comm_convert_color_fmt(inst->fmts[CAPTURE_PORT].fourcc); return VENUS_BUFFER_SIZE(hfi_fmt, inst->prop.width[CAPTURE_PORT], inst->prop.height[CAPTURE_PORT]); } u32 msm_vidc_calculate_dec_output_extra_size(struct msm_vidc_inst *inst) { return VENUS_EXTRADATA_SIZE(inst->prop.height[CAPTURE_PORT], inst->prop.width[CAPTURE_PORT]); } u32 msm_vidc_calculate_enc_input_frame_size(struct msm_vidc_inst *inst) { u32 hfi_fmt; hfi_fmt = msm_comm_convert_color_fmt(inst->fmts[OUTPUT_PORT].fourcc); return VENUS_BUFFER_SIZE(hfi_fmt, inst->prop.width[OUTPUT_PORT], inst->prop.height[OUTPUT_PORT]); } u32 msm_vidc_calculate_enc_output_frame_size(struct msm_vidc_inst *inst) { u32 frame_size; u32 mbs_per_frame; u32 width, height; /* * Encoder output size calculation: * For resolution < 720p : YUVsize * 4 * For resolution > 720p & <= 4K : YUVsize / 2 * For resolution > 4k : YUVsize / 4 */ width = inst->prop.width[CAPTURE_PORT]; height = inst->prop.height[CAPTURE_PORT]; mbs_per_frame = ((width + 15) >> 4) * ((height + 15) >> 4); frame_size = (width * height * 3) >> 1; if (mbs_per_frame < NUM_MBS_720P) frame_size = frame_size << 2; else if (mbs_per_frame <= NUM_MBS_4k) frame_size = frame_size >> 1; else frame_size = frame_size >> 2; if ((inst->rc_type == RATE_CONTROL_OFF) || (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)) frame_size = frame_size << 1; return ALIGN(frame_size, SZ_4K); } static inline u32 ROI_EXTRADATA_SIZE( u32 width, u32 height, u32 lcu_size) { u32 lcu_width = 0; u32 lcu_height = 0; u32 n_shift = 0; while (lcu_size && !(lcu_size & 0x1)) { n_shift++; lcu_size = lcu_size >> 1; } lcu_width = (width + (lcu_size - 1)) >> n_shift; lcu_height = (height + (lcu_size - 1)) >> n_shift; return (((lcu_width + 7) >> 3) << 3) * lcu_height * 2; } u32 msm_vidc_calculate_enc_input_extra_size(struct msm_vidc_inst *inst) { u32 size = 0; u32 width = inst->prop.width[OUTPUT_PORT]; u32 height = inst->prop.height[OUTPUT_PORT]; u32 extradata_count = 0; u32 extra_types; struct v4l2_ctrl *extradata_ctrl; extradata_ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA); extra_types = extradata_ctrl->val; /* Add size for default extradata */ size += sizeof(struct msm_vidc_enc_cvp_metadata_payload); extradata_count++; if (extra_types & EXTRADATA_ENC_INPUT_ROI) { u32 lcu_size = 16; if (inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_HEVC) lcu_size = 32; size += ROI_EXTRADATA_SIZE(width, height, lcu_size); extradata_count++; } if (extra_types & EXTRADATA_ENC_INPUT_HDR10PLUS) { size += sizeof(struct hfi_hdr10_pq_sei); extradata_count++; } /* Add extradata header sizes including EXTRADATA_NONE */ if (size) size += sizeof(struct msm_vidc_extradata_header) * (extradata_count + 1); return ALIGN(size, SZ_4K); } u32 msm_vidc_calculate_enc_output_extra_size(struct msm_vidc_inst *inst) { u32 size = 0; u32 extra_types; struct v4l2_ctrl *extradata_ctrl; extradata_ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA); extra_types = extradata_ctrl->val; if (extra_types & EXTRADATA_ADVANCED) size += sizeof(struct msm_vidc_metadata_ltr_payload); /* Add size for extradata none */ if (size) size += sizeof(struct msm_vidc_extradata_header); return ALIGN(size, SZ_4K); } static inline u32 size_vpss_lb(u32 width, u32 height) { u32 vpss_4tap_top_buffer_size, vpss_div2_top_buffer_size; Loading drivers/media/platform/msm/vidc/msm_vidc_buffer_calculations.h 0 → 100644 +41 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019, The Linux Foundation. All rights reserved. */ #ifndef __H_MSM_VIDC_BUFFER_MEM_DEFS_H__ #define __H_MSM_VIDC_BUFFER_MEM_DEFS_H__ struct msm_vidc_dec_buff_size_calculators { u32 (*calculate_scratch_size)(struct msm_vidc_inst *inst, u32 width, u32 height, bool is_interlaced); u32 (*calculate_scratch1_size)(struct msm_vidc_inst *inst, u32 width, u32 height, u32 min_buf_count, bool split_mode_enabled); u32 (*calculate_persist1_size)(void); }; struct msm_vidc_enc_buff_size_calculators { u32 (*calculate_scratch_size)(struct msm_vidc_inst *inst, u32 width, u32 height, u32 work_mode); u32 (*calculate_scratch1_size)(struct msm_vidc_inst *inst, u32 width, u32 height, u32 num_ref, bool ten_bit, u32 num_vpp_pipes); u32 (*calculate_scratch2_size)(struct msm_vidc_inst *inst, u32 width, u32 height, u32 num_ref, bool ten_bit); u32 (*calculate_persist_size)(void); }; void msm_vidc_init_buffer_size_calculators(struct msm_vidc_inst *inst); int msm_vidc_init_buffer_count(struct msm_vidc_inst *inst); int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst, enum hal_buffer buffer_type); u32 msm_vidc_calculate_dec_input_frame_size(struct msm_vidc_inst *inst); u32 msm_vidc_calculate_dec_output_frame_size(struct msm_vidc_inst *inst); u32 msm_vidc_calculate_dec_output_extra_size(struct msm_vidc_inst *inst); u32 msm_vidc_calculate_enc_input_frame_size(struct msm_vidc_inst *inst); u32 msm_vidc_calculate_enc_output_frame_size(struct msm_vidc_inst *inst); u32 msm_vidc_calculate_enc_input_extra_size(struct msm_vidc_inst *inst); u32 msm_vidc_calculate_enc_output_extra_size(struct msm_vidc_inst *inst); u32 msm_vidc_set_buffer_count_for_thumbnail(struct msm_vidc_inst *inst); #endif // __H_MSM_VIDC_BUFFER_MEM_DEFS_H__ drivers/media/platform/msm/vidc/msm_vidc_clocks.c +1 −41 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ #include "vidc_hfi_api.h" #include "msm_vidc_debug.h" #include "msm_vidc_clocks.h" #include "msm_vidc_buffer_calculations.h" #define MSM_VIDC_MIN_UBWC_COMPLEXITY_FACTOR (1 << 16) #define MSM_VIDC_MAX_UBWC_COMPLEXITY_FACTOR (4 << 16) Loading Loading @@ -1182,47 +1183,6 @@ void msm_clock_data_reset(struct msm_vidc_inst *inst) __func__); } int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst, enum hal_buffer buffer_type) { unsigned int count = 0; if (!inst || !inst->core) { dprintk(VIDC_ERR, "%s Invalid args\n", __func__); return 0; } /* * no extra buffers for thumbnail session because * neither dcvs nor batching will be enabled */ if (is_thumbnail_session(inst)) return 0; /* Add DCVS extra buffer count */ if (inst->core->resources.dcvs) { if (is_decode_session(inst) && buffer_type == HAL_BUFFER_OUTPUT) { count += DCVS_DEC_EXTRA_OUTPUT_BUFFERS; } else if ((is_encode_session(inst) && buffer_type == HAL_BUFFER_INPUT)) { count += DCVS_ENC_EXTRA_INPUT_BUFFERS; } } /* * if platform supports decode batching ensure minimum * batch size count of extra buffers added on output port */ if (buffer_type == HAL_BUFFER_OUTPUT) { if (inst->core->resources.decode_batching && is_decode_session(inst) && count < inst->batch.size) count = inst->batch.size; } return count; } int msm_vidc_decide_work_route_iris1(struct msm_vidc_inst *inst) { int rc = 0; Loading Loading
drivers/media/platform/msm/vidc/msm_vdec.c +9 −95 Original line number Diff line number Diff line Loading @@ -13,16 +13,13 @@ #include "vidc_hfi_api.h" #include "msm_vidc_debug.h" #include "msm_vidc_clocks.h" #include "msm_vidc_buffer_calculations.h" #define MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS MIN_NUM_OUTPUT_BUFFERS #define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS MIN_NUM_CAPTURE_BUFFERS #define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9 8 #define MIN_NUM_DEC_OUTPUT_BUFFERS 4 #define MIN_NUM_DEC_CAPTURE_BUFFERS 4 /* Y=16(0-9bits), Cb(10-19bits)=Cr(20-29bits)=128, black by default */ #define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8020010 #define MAX_VP9D_INST_COUNT 6 #define MAX_4K_MBPF 38736 /* (4096 * 2304 / 256) */ static const char *const vp8_profile_level[] = { "Unused", Loading Loading @@ -454,61 +451,6 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = { #define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls) static u32 get_dec_input_frame_size(struct msm_vidc_inst *inst) { u32 frame_size, num_mbs; u32 div_factor = 1; u32 base_res_mbs = MAX_4K_MBPF; u32 width = inst->prop.width[OUTPUT_PORT]; u32 height = inst->prop.height[OUTPUT_PORT]; /* * Decoder input size calculation: * If clip is 8k buffer size is calculated for 8k : 8k mbs/4 * For 8k cases we expect width/height to be set always. * In all other cases size is calculated for 4k: * 4k mbs for VP8/VP9 and 4k/2 for remaining codecs */ num_mbs = ((width + 15) >> 4) * ((height + 15) >> 4); if (num_mbs > MAX_4K_MBPF) { div_factor = 4; base_res_mbs = inst->capability.mbs_per_frame.max; } else { base_res_mbs = MAX_4K_MBPF; if (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) div_factor = 1; else div_factor = 2; } frame_size = base_res_mbs * 3 / 2 / div_factor; /* multiply by 10/8 (1.25) to get size for 10 bit case */ if ((inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) || (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_HEVC)) frame_size = frame_size + (frame_size >> 2); if (inst->buffer_size_limit && (inst->buffer_size_limit < frame_size)) { frame_size = inst->buffer_size_limit; dprintk(VIDC_DBG, "input buffer size limited to %d\n", frame_size); } else { dprintk(VIDC_DBG, "set input buffer size to %d\n", frame_size); } return ALIGN(frame_size, SZ_4K); } static u32 get_dec_output_frame_size(struct msm_vidc_inst *inst) { u32 hfi_fmt; hfi_fmt = msm_comm_convert_color_fmt(inst->fmts[CAPTURE_PORT].fourcc); return VENUS_BUFFER_SIZE(hfi_fmt, inst->prop.width[CAPTURE_PORT], inst->prop.height[CAPTURE_PORT]); } struct msm_vidc_format vdec_formats[] = { { .name = "YCbCr Semiplanar 4:2:0", Loading Loading @@ -701,7 +643,7 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) } f->fmt.pix_mp.plane_fmt[0].sizeimage = get_dec_output_frame_size(inst); msm_vidc_calculate_dec_output_frame_size(inst); extra_idx = EXTRADATA_IDX(inst->bufq[fmt->type].num_planes); if (extra_idx && extra_idx < VIDEO_MAX_PLANES) { Loading Loading @@ -770,7 +712,7 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) goto err_invalid_fmt; } max_input_size = get_dec_input_frame_size(inst); max_input_size = msm_vidc_calculate_dec_input_frame_size(inst); if (f->fmt.pix_mp.plane_fmt[0].sizeimage > max_input_size || !f->fmt.pix_mp.plane_fmt[0].sizeimage) { f->fmt.pix_mp.plane_fmt[0].sizeimage = max_input_size; Loading Loading @@ -845,9 +787,8 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) inst->bufq[OUTPUT_PORT].num_planes = 1; inst->bufq[CAPTURE_PORT].num_planes = 2; inst->bufq[CAPTURE_PORT].plane_sizes[1] = VENUS_EXTRADATA_SIZE( inst->prop.height[CAPTURE_PORT], inst->prop.width[CAPTURE_PORT]); msm_vidc_calculate_dec_output_extra_size(inst); inst->clk_data.frame_rate = (DEFAULT_FPS << 16); inst->clk_data.operating_rate = (DEFAULT_FPS << 16); if (core->resources.decode_batching) Loading Loading @@ -907,7 +848,6 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) { int rc = 0; struct hal_buffer_requirements *bufreq; if (!inst || !inst->core || !inst->core->device) { dprintk(VIDC_ERR, "%s invalid parameters\n", __func__); Loading Loading @@ -950,36 +890,10 @@ int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) inst->flags |= VIDC_THUMBNAIL; msm_dcvs_try_enable(inst); bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT); if (!bufreq) return -EINVAL; bufreq->buffer_count_min = MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS; bufreq->buffer_count_min_host = MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS; bufreq->buffer_count_actual = MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS; bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT); if (!bufreq) return -EINVAL; /* VP9 super frame requires multiple frames decoding */ if (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) { bufreq->buffer_count_min = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9; bufreq->buffer_count_min_host = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9; bufreq->buffer_count_actual = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9; } else { bufreq->buffer_count_min = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS; bufreq->buffer_count_min_host = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS; bufreq->buffer_count_actual = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS; rc = msm_vidc_set_buffer_count_for_thumbnail(inst); if (rc) { dprintk(VIDC_ERR, "Failed to set buffer count\n"); return rc; } break; case V4L2_CID_MPEG_VIDC_VIDEO_SECURE: Loading
drivers/media/platform/msm/vidc/msm_venc.c +12 −115 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #include "vidc_hfi_api.h" #include "msm_vidc_debug.h" #include "msm_vidc_clocks.h" #include "msm_vidc_buffer_calculations.h" #define MIN_BIT_RATE 32000 #define MAX_BIT_RATE 1200000000 Loading @@ -18,9 +19,7 @@ #define BIT_RATE_STEP 1 #define MAX_SLICE_BYTE_SIZE ((MAX_BIT_RATE)>>3) #define MIN_SLICE_BYTE_SIZE 512 #define NUM_MBS_720P (((1280 + 15) >> 4) * ((720 + 15) >> 4)) #define NUM_MBS_4k (((4096 + 15) >> 4) * ((2304 + 15) >> 4)) #define MAX_SLICE_MB_SIZE NUM_MBS_4k #define MAX_SLICE_MB_SIZE (((4096 + 15) >> 4) * ((2304 + 15) >> 4)) #define QP_ENABLE_I 0x1 #define QP_ENABLE_P 0x2 #define QP_ENABLE_B 0x4 Loading Loading @@ -943,110 +942,6 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = { #define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls) static u32 get_enc_input_frame_size(struct msm_vidc_inst *inst) { u32 hfi_fmt; hfi_fmt = msm_comm_convert_color_fmt(inst->fmts[OUTPUT_PORT].fourcc); return VENUS_BUFFER_SIZE(hfi_fmt, inst->prop.width[OUTPUT_PORT], inst->prop.height[OUTPUT_PORT]); } static u32 get_enc_output_frame_size(struct msm_vidc_inst *inst) { u32 frame_size; u32 mbs_per_frame; u32 width, height; /* * Encoder output size calculation: * For resolution < 720p : YUVsize * 4 * For resolution > 720p & <= 4K : YUVsize / 2 * For resolution > 4k : YUVsize / 4 */ width = inst->prop.width[CAPTURE_PORT]; height = inst->prop.height[CAPTURE_PORT]; mbs_per_frame = ((width + 15) >> 4) * ((height + 15) >> 4); frame_size = (width * height * 3) >> 1; if (mbs_per_frame < NUM_MBS_720P) frame_size = frame_size << 2; else if (mbs_per_frame <= NUM_MBS_4k) frame_size = frame_size >> 1; else frame_size = frame_size >> 2; if ((inst->rc_type == RATE_CONTROL_OFF) || (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)) frame_size = frame_size << 1; return ALIGN(frame_size, SZ_4K); } static inline u32 ROI_EXTRADATA_SIZE( u32 width, u32 height, u32 lcu_size) { u32 lcu_width = 0; u32 lcu_height = 0; u32 n_shift = 0; while (lcu_size && !(lcu_size & 0x1)) { n_shift++; lcu_size = lcu_size >> 1; } lcu_width = (width + (lcu_size - 1)) >> n_shift; lcu_height = (height + (lcu_size - 1)) >> n_shift; return (((lcu_width + 7) >> 3) << 3) * lcu_height * 2; } static u32 get_enc_input_extra_size(struct msm_vidc_inst *inst, u32 extra_types) { u32 size = 0; u32 width = inst->prop.width[OUTPUT_PORT]; u32 height = inst->prop.height[OUTPUT_PORT]; u32 extradata_count = 0; /* Add size for default extradata */ size += sizeof(struct msm_vidc_enc_cvp_metadata_payload); extradata_count++; if (extra_types & EXTRADATA_ENC_INPUT_ROI) { u32 lcu_size = 16; if (inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_HEVC) lcu_size = 32; size += ROI_EXTRADATA_SIZE(width, height, lcu_size); extradata_count++; } if (extra_types & EXTRADATA_ENC_INPUT_HDR10PLUS) { size += sizeof(struct hfi_hdr10_pq_sei); extradata_count++; } /* Add extradata header sizes including EXTRADATA_NONE */ if (size) size += sizeof(struct msm_vidc_extradata_header) * (extradata_count + 1); return ALIGN(size, SZ_4K); } static u32 get_enc_output_extra_size(struct msm_vidc_inst *inst, u32 extra_types) { u32 size = 0; if (extra_types & EXTRADATA_ADVANCED) size += sizeof(struct msm_vidc_metadata_ltr_payload); /* Add size for extradata none */ if (size) size += sizeof(struct msm_vidc_extradata_header); return ALIGN(size, SZ_4K); } static struct msm_vidc_format venc_formats[] = { { .name = "YCbCr Semiplanar 4:2:0", Loading Loading @@ -1211,7 +1106,7 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) } buff_req_buffer->buffer_size = get_enc_input_extra_size(inst, EXTRADATA_DEFAULT); msm_vidc_calculate_enc_input_extra_size(inst); inst->bufq[OUTPUT_PORT].plane_sizes[1] = buff_req_buffer->buffer_size; Loading Loading @@ -1368,9 +1263,10 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) * update bitstream buffer size based on width & height * updating extradata buffer size is not required as * it is already updated when extradata control is set * and it is not dependent on frame size */ inst->bufq[fmt->type].plane_sizes[0] = get_enc_output_frame_size(inst); msm_vidc_calculate_enc_output_frame_size(inst); f->fmt.pix_mp.num_planes = inst->bufq[fmt->type].num_planes; for (i = 0; i < inst->bufq[fmt->type].num_planes; i++) { Loading Loading @@ -1403,11 +1299,13 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) /* * update bitstream buffer size based on width & height * updating extradata buffer size is not required as * it is already updated when extradata control is set * update extradata buffer size as it may change due to * frame size change. */ inst->bufq[fmt->type].plane_sizes[0] = get_enc_input_frame_size(inst); msm_vidc_calculate_enc_input_frame_size(inst); inst->bufq[fmt->type].plane_sizes[1] = msm_vidc_calculate_enc_input_extra_size(inst); f->fmt.pix_mp.num_planes = inst->bufq[fmt->type].num_planes; for (i = 0; i < inst->bufq[fmt->type].num_planes; i++) { f->fmt.pix_mp.plane_fmt[i].sizeimage = Loading Loading @@ -1678,8 +1576,7 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) } buff_req_buffer->buffer_size = get_enc_input_extra_size(inst, ctrl->val); msm_vidc_calculate_enc_input_extra_size(inst); inst->bufq[OUTPUT_PORT].plane_sizes[1] = buff_req_buffer->buffer_size; } Loading @@ -1697,7 +1594,7 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) } buff_req_buffer->buffer_size = get_enc_output_extra_size(inst, ctrl->val); msm_vidc_calculate_enc_output_extra_size(inst); inst->bufq[CAPTURE_PORT].plane_sizes[1] = buff_req_buffer->buffer_size; } Loading
drivers/media/platform/msm/vidc/msm_vidc_buffer_calculations.c +335 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,17 @@ #include "msm_vidc_debug.h" #include "msm_vidc_common.h" #include "msm_vidc_buffer_calculations.h" #define MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS MIN_NUM_OUTPUT_BUFFERS #define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS MIN_NUM_CAPTURE_BUFFERS #define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9 8 /* extra o/p buffers in case of encoder dcvs */ #define DCVS_ENC_EXTRA_INPUT_BUFFERS 4 /* extra o/p buffers in case of decoder dcvs */ #define DCVS_DEC_EXTRA_OUTPUT_BUFFERS 4 #define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_WIDTH 32 #define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_HEIGHT 8 Loading Loading @@ -239,6 +250,8 @@ #define HFI_VENUS_HEIGHT_ALIGNMENT 32 #define SYSTEM_LAL_TILE10 192 #define NUM_MBS_720P (((1280 + 15) >> 4) * ((720 + 15) >> 4)) #define NUM_MBS_4k (((4096 + 15) >> 4) * ((2304 + 15) >> 4)) static inline u32 calculate_h264d_scratch_size(struct msm_vidc_inst *inst, u32 width, u32 height, bool is_interlaced); Loading Loading @@ -577,6 +590,328 @@ void msm_vidc_init_buffer_size_calculators(struct msm_vidc_inst *inst) msm_vidc_calculate_internal_buffer_sizes; } int msm_vidc_init_buffer_count(struct msm_vidc_inst *inst) { int extra_buff_count = 0; struct hal_buffer_requirements *bufreq; int port; if (!is_decode_session(inst) && !is_encode_session(inst)) return 0; if (is_decode_session(inst)) port = OUTPUT_PORT; else port = CAPTURE_PORT; /* Update input buff counts */ bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT); if (!bufreq) return -EINVAL; extra_buff_count = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_INPUT); bufreq->buffer_count_min = inst->fmts[port].input_min_count; /* batching needs minimum batch size count of input buffers */ if (inst->core->resources.decode_batching && is_decode_session(inst) && bufreq->buffer_count_min < inst->batch.size) bufreq->buffer_count_min = inst->batch.size; bufreq->buffer_count_min_host = bufreq->buffer_count_actual = bufreq->buffer_count_min + extra_buff_count; dprintk(VIDC_DBG, "%s: %x : input min %d min_host %d actual %d\n", __func__, hash32_ptr(inst->session), bufreq->buffer_count_min, bufreq->buffer_count_min_host, bufreq->buffer_count_actual); bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT); if (!bufreq) return -EINVAL; bufreq->buffer_count_min = inst->fmts[port].input_min_count; bufreq->buffer_count_min_host = bufreq->buffer_count_actual = bufreq->buffer_count_min + extra_buff_count; /* Update output buff count */ bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT); if (!bufreq) return -EINVAL; extra_buff_count = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_OUTPUT); bufreq->buffer_count_min = inst->fmts[port].output_min_count; bufreq->buffer_count_min_host = bufreq->buffer_count_actual = bufreq->buffer_count_min + extra_buff_count; dprintk(VIDC_DBG, "%s: %x : output min %d min_host %d actual %d\n", __func__, hash32_ptr(inst->session), bufreq->buffer_count_min, bufreq->buffer_count_min_host, bufreq->buffer_count_actual); bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_OUTPUT); if (!bufreq) return -EINVAL; bufreq->buffer_count_min = inst->fmts[port].output_min_count; bufreq->buffer_count_min_host = bufreq->buffer_count_actual = bufreq->buffer_count_min + extra_buff_count; return 0; } u32 msm_vidc_set_buffer_count_for_thumbnail(struct msm_vidc_inst *inst) { struct hal_buffer_requirements *bufreq; bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT); if (!bufreq) return -EINVAL; bufreq->buffer_count_min = MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS; bufreq->buffer_count_min_host = MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS; bufreq->buffer_count_actual = MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS; bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT); if (!bufreq) return -EINVAL; /* VP9 super frame requires multiple frames decoding */ if (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) { bufreq->buffer_count_min = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9; bufreq->buffer_count_min_host = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9; bufreq->buffer_count_actual = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS_VP9; } else { bufreq->buffer_count_min = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS; bufreq->buffer_count_min_host = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS; bufreq->buffer_count_actual = MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS; } return 0; } int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst, enum hal_buffer buffer_type) { unsigned int count = 0; if (!inst || !inst->core) { dprintk(VIDC_ERR, "%s Invalid args\n", __func__); return 0; } /* * no extra buffers for thumbnail session because * neither dcvs nor batching will be enabled */ if (is_thumbnail_session(inst)) return 0; /* Add DCVS extra buffer count */ if (inst->core->resources.dcvs) { if (is_decode_session(inst) && buffer_type == HAL_BUFFER_OUTPUT) { count += DCVS_DEC_EXTRA_OUTPUT_BUFFERS; } else if ((is_encode_session(inst) && buffer_type == HAL_BUFFER_INPUT)) { count += DCVS_ENC_EXTRA_INPUT_BUFFERS; } } /* * if platform supports decode batching ensure minimum * batch size count of extra buffers added on output port */ if (buffer_type == HAL_BUFFER_OUTPUT) { if (inst->core->resources.decode_batching && is_decode_session(inst) && count < inst->batch.size) count = inst->batch.size; } return count; } u32 msm_vidc_calculate_dec_input_frame_size(struct msm_vidc_inst *inst) { u32 frame_size, num_mbs; u32 div_factor = 1; u32 base_res_mbs = NUM_MBS_4k; u32 width = inst->prop.width[OUTPUT_PORT]; u32 height = inst->prop.height[OUTPUT_PORT]; /* * Decoder input size calculation: * If clip is 8k buffer size is calculated for 8k : 8k mbs/4 * For 8k cases we expect width/height to be set always. * In all other cases size is calculated for 4k: * 4k mbs for VP8/VP9 and 4k/2 for remaining codecs */ num_mbs = ((width + 15) >> 4) * ((height + 15) >> 4); if (num_mbs > NUM_MBS_4k) { div_factor = 4; base_res_mbs = inst->capability.mbs_per_frame.max; } else { base_res_mbs = NUM_MBS_4k; if (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) div_factor = 1; else div_factor = 2; } frame_size = base_res_mbs * 3 / 2 / div_factor; /* multiply by 10/8 (1.25) to get size for 10 bit case */ if ((inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9) || (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_HEVC)) frame_size = frame_size + (frame_size >> 2); if (inst->buffer_size_limit && (inst->buffer_size_limit < frame_size)) { frame_size = inst->buffer_size_limit; dprintk(VIDC_DBG, "input buffer size limited to %d\n", frame_size); } else { dprintk(VIDC_DBG, "set input buffer size to %d\n", frame_size); } return ALIGN(frame_size, SZ_4K); } u32 msm_vidc_calculate_dec_output_frame_size(struct msm_vidc_inst *inst) { u32 hfi_fmt; hfi_fmt = msm_comm_convert_color_fmt(inst->fmts[CAPTURE_PORT].fourcc); return VENUS_BUFFER_SIZE(hfi_fmt, inst->prop.width[CAPTURE_PORT], inst->prop.height[CAPTURE_PORT]); } u32 msm_vidc_calculate_dec_output_extra_size(struct msm_vidc_inst *inst) { return VENUS_EXTRADATA_SIZE(inst->prop.height[CAPTURE_PORT], inst->prop.width[CAPTURE_PORT]); } u32 msm_vidc_calculate_enc_input_frame_size(struct msm_vidc_inst *inst) { u32 hfi_fmt; hfi_fmt = msm_comm_convert_color_fmt(inst->fmts[OUTPUT_PORT].fourcc); return VENUS_BUFFER_SIZE(hfi_fmt, inst->prop.width[OUTPUT_PORT], inst->prop.height[OUTPUT_PORT]); } u32 msm_vidc_calculate_enc_output_frame_size(struct msm_vidc_inst *inst) { u32 frame_size; u32 mbs_per_frame; u32 width, height; /* * Encoder output size calculation: * For resolution < 720p : YUVsize * 4 * For resolution > 720p & <= 4K : YUVsize / 2 * For resolution > 4k : YUVsize / 4 */ width = inst->prop.width[CAPTURE_PORT]; height = inst->prop.height[CAPTURE_PORT]; mbs_per_frame = ((width + 15) >> 4) * ((height + 15) >> 4); frame_size = (width * height * 3) >> 1; if (mbs_per_frame < NUM_MBS_720P) frame_size = frame_size << 2; else if (mbs_per_frame <= NUM_MBS_4k) frame_size = frame_size >> 1; else frame_size = frame_size >> 2; if ((inst->rc_type == RATE_CONTROL_OFF) || (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)) frame_size = frame_size << 1; return ALIGN(frame_size, SZ_4K); } static inline u32 ROI_EXTRADATA_SIZE( u32 width, u32 height, u32 lcu_size) { u32 lcu_width = 0; u32 lcu_height = 0; u32 n_shift = 0; while (lcu_size && !(lcu_size & 0x1)) { n_shift++; lcu_size = lcu_size >> 1; } lcu_width = (width + (lcu_size - 1)) >> n_shift; lcu_height = (height + (lcu_size - 1)) >> n_shift; return (((lcu_width + 7) >> 3) << 3) * lcu_height * 2; } u32 msm_vidc_calculate_enc_input_extra_size(struct msm_vidc_inst *inst) { u32 size = 0; u32 width = inst->prop.width[OUTPUT_PORT]; u32 height = inst->prop.height[OUTPUT_PORT]; u32 extradata_count = 0; u32 extra_types; struct v4l2_ctrl *extradata_ctrl; extradata_ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA); extra_types = extradata_ctrl->val; /* Add size for default extradata */ size += sizeof(struct msm_vidc_enc_cvp_metadata_payload); extradata_count++; if (extra_types & EXTRADATA_ENC_INPUT_ROI) { u32 lcu_size = 16; if (inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_HEVC) lcu_size = 32; size += ROI_EXTRADATA_SIZE(width, height, lcu_size); extradata_count++; } if (extra_types & EXTRADATA_ENC_INPUT_HDR10PLUS) { size += sizeof(struct hfi_hdr10_pq_sei); extradata_count++; } /* Add extradata header sizes including EXTRADATA_NONE */ if (size) size += sizeof(struct msm_vidc_extradata_header) * (extradata_count + 1); return ALIGN(size, SZ_4K); } u32 msm_vidc_calculate_enc_output_extra_size(struct msm_vidc_inst *inst) { u32 size = 0; u32 extra_types; struct v4l2_ctrl *extradata_ctrl; extradata_ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA); extra_types = extradata_ctrl->val; if (extra_types & EXTRADATA_ADVANCED) size += sizeof(struct msm_vidc_metadata_ltr_payload); /* Add size for extradata none */ if (size) size += sizeof(struct msm_vidc_extradata_header); return ALIGN(size, SZ_4K); } static inline u32 size_vpss_lb(u32 width, u32 height) { u32 vpss_4tap_top_buffer_size, vpss_div2_top_buffer_size; Loading
drivers/media/platform/msm/vidc/msm_vidc_buffer_calculations.h 0 → 100644 +41 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019, The Linux Foundation. All rights reserved. */ #ifndef __H_MSM_VIDC_BUFFER_MEM_DEFS_H__ #define __H_MSM_VIDC_BUFFER_MEM_DEFS_H__ struct msm_vidc_dec_buff_size_calculators { u32 (*calculate_scratch_size)(struct msm_vidc_inst *inst, u32 width, u32 height, bool is_interlaced); u32 (*calculate_scratch1_size)(struct msm_vidc_inst *inst, u32 width, u32 height, u32 min_buf_count, bool split_mode_enabled); u32 (*calculate_persist1_size)(void); }; struct msm_vidc_enc_buff_size_calculators { u32 (*calculate_scratch_size)(struct msm_vidc_inst *inst, u32 width, u32 height, u32 work_mode); u32 (*calculate_scratch1_size)(struct msm_vidc_inst *inst, u32 width, u32 height, u32 num_ref, bool ten_bit, u32 num_vpp_pipes); u32 (*calculate_scratch2_size)(struct msm_vidc_inst *inst, u32 width, u32 height, u32 num_ref, bool ten_bit); u32 (*calculate_persist_size)(void); }; void msm_vidc_init_buffer_size_calculators(struct msm_vidc_inst *inst); int msm_vidc_init_buffer_count(struct msm_vidc_inst *inst); int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst, enum hal_buffer buffer_type); u32 msm_vidc_calculate_dec_input_frame_size(struct msm_vidc_inst *inst); u32 msm_vidc_calculate_dec_output_frame_size(struct msm_vidc_inst *inst); u32 msm_vidc_calculate_dec_output_extra_size(struct msm_vidc_inst *inst); u32 msm_vidc_calculate_enc_input_frame_size(struct msm_vidc_inst *inst); u32 msm_vidc_calculate_enc_output_frame_size(struct msm_vidc_inst *inst); u32 msm_vidc_calculate_enc_input_extra_size(struct msm_vidc_inst *inst); u32 msm_vidc_calculate_enc_output_extra_size(struct msm_vidc_inst *inst); u32 msm_vidc_set_buffer_count_for_thumbnail(struct msm_vidc_inst *inst); #endif // __H_MSM_VIDC_BUFFER_MEM_DEFS_H__
drivers/media/platform/msm/vidc/msm_vidc_clocks.c +1 −41 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ #include "vidc_hfi_api.h" #include "msm_vidc_debug.h" #include "msm_vidc_clocks.h" #include "msm_vidc_buffer_calculations.h" #define MSM_VIDC_MIN_UBWC_COMPLEXITY_FACTOR (1 << 16) #define MSM_VIDC_MAX_UBWC_COMPLEXITY_FACTOR (4 << 16) Loading Loading @@ -1182,47 +1183,6 @@ void msm_clock_data_reset(struct msm_vidc_inst *inst) __func__); } int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst, enum hal_buffer buffer_type) { unsigned int count = 0; if (!inst || !inst->core) { dprintk(VIDC_ERR, "%s Invalid args\n", __func__); return 0; } /* * no extra buffers for thumbnail session because * neither dcvs nor batching will be enabled */ if (is_thumbnail_session(inst)) return 0; /* Add DCVS extra buffer count */ if (inst->core->resources.dcvs) { if (is_decode_session(inst) && buffer_type == HAL_BUFFER_OUTPUT) { count += DCVS_DEC_EXTRA_OUTPUT_BUFFERS; } else if ((is_encode_session(inst) && buffer_type == HAL_BUFFER_INPUT)) { count += DCVS_ENC_EXTRA_INPUT_BUFFERS; } } /* * if platform supports decode batching ensure minimum * batch size count of extra buffers added on output port */ if (buffer_type == HAL_BUFFER_OUTPUT) { if (inst->core->resources.decode_batching && is_decode_session(inst) && count < inst->batch.size) count = inst->batch.size; } return count; } int msm_vidc_decide_work_route_iris1(struct msm_vidc_inst *inst) { int rc = 0; Loading