Merge "msm: vidc: add superframe encode support"

This commit is contained in:
qctecmdr 2019-06-24 11:21:20 -07:00 • committed by Gerrit - the friendly Code Review server
commit a108e35d45
9 changed files with 192 additions and 3 deletions

View file

@ -876,6 +876,7 @@ static struct hfi_packetization_ops hfi_default = {
.session_get_buf_req = create_pkt_cmd_session_get_buf_req,
.session_flush = create_pkt_cmd_session_flush,
.session_set_property = create_pkt_cmd_session_set_property,
.session_sync_process = create_pkt_cmd_session_sync_process,
};
struct hfi_packetization_ops *hfi_get_pkt_ops_handle(

View file

@ -397,6 +397,15 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = {
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
.step = 1,
},
{
.id = V4L2_CID_MPEG_VIDC_SUPERFRAME,
.name = "Superframe",
.type = V4L2_CTRL_TYPE_INTEGER,
.minimum = 0,
.maximum = 0,
.default_value = 0,
.step = 1,
},
};
#define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls)

View file

@ -948,6 +948,15 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
.default_value = 0,
.step = 500,
},
{
.id = V4L2_CID_MPEG_VIDC_SUPERFRAME,
.name = "Superframe",
.type = V4L2_CTRL_TYPE_INTEGER,
.minimum = 0,
.maximum = VIDC_SUPERFRAME_MAX,
.default_value = 0,
.step = 1,
},
};
#define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls)
@ -1798,6 +1807,7 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
case V4L2_CID_MPEG_VIDC_VENC_RC_TIMESTAMP_DISABLE:
case V4L2_CID_MPEG_VIDEO_VBV_DELAY:
case V4L2_CID_MPEG_VIDC_VENC_BITRATE_SAVINGS:
case V4L2_CID_MPEG_VIDC_SUPERFRAME:
dprintk(VIDC_HIGH, "Control set: ID : %x Val : %d\n",
ctrl->id, ctrl->val);
break;
@ -2166,6 +2176,12 @@ void msm_venc_decide_bframe(struct msm_vidc_inst *inst)
goto disable_bframe;
}
}
/* do not enable bframe if superframe is enabled */
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_SUPERFRAME);
if (ctrl->val)
goto disable_bframe;
dprintk(VIDC_HIGH, "Bframe can be enabled!\n");
return;

View file

@ -18,6 +18,10 @@
/* extra o/p buffers in case of decoder dcvs */
#define DCVS_DEC_EXTRA_OUTPUT_BUFFERS 4
/* extra buffers for encoder HFR usecase */
#define HFR_EXTRA_INPUT_BUFFERS 4
#define HFR_EXTRA_OUTPUT_BUFFERS 12
#define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_WIDTH 32
#define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_Y_TILE_HEIGHT 8
#define HFI_COLOR_FORMAT_YUV420_NV12_UBWC_UV_TILE_WIDTH 16
@ -724,6 +728,7 @@ int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst,
enum hal_buffer buffer_type)
{
unsigned int count = 0;
struct v4l2_format *f;
if (!inst || !inst->core) {
dprintk(VIDC_ERR, "%s Invalid args\n", __func__);
@ -758,6 +763,19 @@ int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst,
count = inst->batch.size;
}
/* increase both input and output counts for HFR/HSR encode case */
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
if (is_encode_session(inst) && msm_vidc_get_fps(inst) >= 120 &&
!res_is_greater_than(f->fmt.pix_mp.width,
f->fmt.pix_mp.height, 1920, 1088)) {
if (buffer_type == HAL_BUFFER_INPUT &&
count < HFR_EXTRA_INPUT_BUFFERS)
count = HFR_EXTRA_INPUT_BUFFERS;
if (buffer_type == HAL_BUFFER_OUTPUT &&
count < HFR_EXTRA_OUTPUT_BUFFERS)
count = HFR_EXTRA_OUTPUT_BUFFERS;
}
return count;
}

View file

@ -160,7 +160,7 @@ int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst)
return NUM_MBS_PER_FRAME(height, width);
}
static int msm_vidc_get_fps(struct msm_vidc_inst *inst)
int msm_vidc_get_fps(struct msm_vidc_inst *inst)
{
int fps;
@ -176,10 +176,16 @@ static int msm_vidc_get_fps(struct msm_vidc_inst *inst)
void update_recon_stats(struct msm_vidc_inst *inst,
struct recon_stats_type *recon_stats)
{
struct v4l2_ctrl *ctrl;
struct recon_buf *binfo;
u32 CR = 0, CF = 0;
u32 frame_size;
/* do not consider recon stats in case of superframe */
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_SUPERFRAME);
if (ctrl->val)
return;
CR = get_ubwc_compression_ratio(recon_stats->ubwc_stats_info);
frame_size = (msm_vidc_get_mbs_per_frame(inst) / (32 * 8) * 3) / 2;

View file

@ -18,6 +18,7 @@ bool res_is_less_than_or_equal_to(u32 width, u32 height,
bool res_is_greater_than_or_equal_to(u32 width, u32 height,
u32 ref_width, u32 ref_height);
int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst);
int msm_vidc_get_fps(struct msm_vidc_inst *inst);
int msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst);
int msm_comm_init_clocks_and_bus_data(struct msm_vidc_inst *inst);
void msm_comm_free_freq_table(struct msm_vidc_inst *inst);
@ -36,4 +37,8 @@ void msm_comm_update_input_cr(struct msm_vidc_inst *inst, u32 index,
void update_recon_stats(struct msm_vidc_inst *inst,
struct recon_stats_type *recon_stats);
void msm_vidc_init_core_clk_ops(struct msm_vidc_core *core);
bool res_is_greater_than(u32 width, u32 height,
u32 ref_width, u32 ref_height);
bool res_is_less_than(u32 width, u32 height,
u32 ref_width, u32 ref_height);
#endif

View file

@ -2436,6 +2436,7 @@ static void handle_ebd(enum hal_command_response cmd, void *data)
struct vidc_hal_ebd *empty_buf_done;
u32 planes[VIDEO_MAX_PLANES] = {0};
struct v4l2_format *f;
struct v4l2_ctrl *ctrl;
if (!response) {
dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
@ -2468,9 +2469,23 @@ static void handle_ebd(enum hal_command_response cmd, void *data)
__func__, planes[0], planes[1]);
goto exit;
}
mbuf->flags &= ~MSM_VIDC_FLAG_QUEUED;
vb = &mbuf->vvb.vb2_buf;
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_SUPERFRAME);
if (ctrl->val && empty_buf_done->offset +
empty_buf_done->filled_len < vb->planes[0].length) {
dprintk(VIDC_HIGH,
"%s: %x : addr (%#x): offset (%d) + filled_len (%d) < length (%d)\n",
__func__, hash32_ptr(inst->session),
empty_buf_done->packet_buffer,
empty_buf_done->offset,
empty_buf_done->filled_len,
vb->planes[0].length);
kref_put_mbuf(mbuf);
goto exit;
}
mbuf->flags &= ~MSM_VIDC_FLAG_QUEUED;
vb->planes[0].bytesused = response->input_done.filled_len;
if (vb->planes[0].bytesused > vb->planes[0].length)
dprintk(VIDC_LOW, "bytesused overflow length\n");
@ -4315,6 +4330,98 @@ err_bad_input:
return rc;
}
static int msm_comm_qbuf_superframe_to_hfi(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *mbuf)
{
int rc, i;
struct hfi_device *hdev;
struct v4l2_format *f;
struct v4l2_ctrl *ctrl;
u64 ts_delta_us;
struct vidc_frame_data *frames;
u32 num_etbs, superframe_count, frame_size, hfi_fmt;
if (!inst || !inst->core || !inst->core->device || !mbuf) {
dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
return -EINVAL;
}
hdev = inst->core->device;
frames = inst->superframe_data;
if (!is_input_buffer(mbuf))
return msm_comm_qbuf_to_hfi(inst, mbuf);
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_SUPERFRAME);
superframe_count = ctrl->val;
if (superframe_count > VIDC_SUPERFRAME_MAX) {
dprintk(VIDC_ERR, "%s: wrong superframe count %d, max %d\n",
__func__, superframe_count, VIDC_SUPERFRAME_MAX);
return -EINVAL;
}
ts_delta_us = 1000000 / (inst->clk_data.frame_rate >> 16);
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
hfi_fmt = msm_comm_convert_color_fmt(f->fmt.pix_mp.pixelformat);
frame_size = VENUS_BUFFER_SIZE(hfi_fmt, f->fmt.pix_mp.width,
f->fmt.pix_mp.height);
if (frame_size * superframe_count !=
mbuf->vvb.vb2_buf.planes[0].length) {
dprintk(VIDC_ERR,
"%s: %#x : invalid superframe length, pxlfmt %#x wxh %dx%d framesize %d count %d length %d\n",
__func__, hash32_ptr(inst->session),
f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width,
f->fmt.pix_mp.height, frame_size, superframe_count,
mbuf->vvb.vb2_buf.planes[0].length);
return -EINVAL;
}
num_etbs = 0;
populate_frame_data(&frames[0], mbuf, inst);
/* prepare superframe buffers */
frames[0].filled_len = frame_size;
/*
* superframe logic updates extradata and eos flags only, so
* ensure no other flags are populated in populate_frame_data()
*/
frames[0].flags &= ~HAL_BUFFERFLAG_EXTRADATA;
frames[0].flags &= ~HAL_BUFFERFLAG_EOS;
if (frames[0].flags)
dprintk(VIDC_ERR, "%s: invalid flags %#x\n",
__func__, frames[0].flags);
frames[0].flags = 0;
for (i = 0; i < superframe_count; i++) {
if (i)
memcpy(&frames[i], &frames[0],
sizeof(struct vidc_frame_data));
frames[i].offset += i * frame_size;
frames[i].timestamp += i * ts_delta_us;
if (!i) {
/* first frame */
if (frames[i].extradata_addr)
frames[i].flags |= HAL_BUFFERFLAG_EXTRADATA;
} else if (i == superframe_count - 1) {
/* last frame */
if (mbuf->vvb.flags & V4L2_BUF_FLAG_EOS)
frames[i].flags |= HAL_BUFFERFLAG_EOS;
}
num_etbs++;
}
rc = call_hfi_op(hdev, session_process_batch, inst->session,
num_etbs, frames, 0, NULL);
if (rc) {
dprintk(VIDC_ERR, "%s: Failed to qbuf: %d\n", __func__, rc);
return rc;
}
/* update mbuf flags */
mbuf->flags |= MSM_VIDC_FLAG_QUEUED;
mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_ETB);
return 0;
}
static int msm_comm_qbuf_in_rbr(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *mbuf)
{
@ -4345,6 +4452,7 @@ static int msm_comm_qbuf_in_rbr(struct msm_vidc_inst *inst,
int msm_comm_qbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
{
int rc = 0;
struct v4l2_ctrl *ctrl;
if (!inst || !mbuf) {
dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
@ -4371,7 +4479,11 @@ int msm_comm_qbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
dprintk(VIDC_ERR, "%s: scale clocks failed\n", __func__);
print_vidc_buffer(VIDC_HIGH, "qbuf", inst, mbuf);
rc = msm_comm_qbuf_to_hfi(inst, mbuf);
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_SUPERFRAME);
if (ctrl->val)
rc = msm_comm_qbuf_superframe_to_hfi(inst, mbuf);
else
rc = msm_comm_qbuf_to_hfi(inst, mbuf);
if (rc)
dprintk(VIDC_ERR, "%s: Failed qbuf to hfi: %d\n", __func__, rc);
@ -4975,14 +5087,23 @@ int msm_comm_set_buffer_count(struct msm_vidc_inst *inst,
int host_count, int act_count, enum hal_buffer type)
{
int rc = 0;
struct v4l2_ctrl *ctrl;
struct hfi_device *hdev;
struct hfi_buffer_count_actual buf_count;
if (!inst || !inst->core || !inst->core->device) {
dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
return -EINVAL;
}
hdev = inst->core->device;
buf_count.buffer_type = get_hfi_buffer(type);
buf_count.buffer_count_actual = act_count;
buf_count.buffer_count_min_host = host_count;
/* set total superframe buffers count */
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_SUPERFRAME);
if (ctrl->val)
buf_count.buffer_count_actual = act_count * ctrl->val;
dprintk(VIDC_HIGH, "%s: %x : hal_buffer %d min_host %d actual %d\n",
__func__, hash32_ptr(inst->session), type,
host_count, act_count);

View file

@ -119,6 +119,16 @@ static inline bool in_port_reconfig(struct msm_vidc_inst *inst)
return inst->in_reconfig && inst->bufq[INPUT_PORT].vb2_bufq.streaming;
}
static inline bool is_input_buffer(struct msm_vidc_buffer *mbuf)
{
return mbuf->vvb.vb2_buf.type == INPUT_MPLANE;
}
static inline bool is_output_buffer(struct msm_vidc_buffer *mbuf)
{
return mbuf->vvb.vb2_buf.type == OUTPUT_MPLANE;
}
static inline int msm_comm_g_ctrl(struct msm_vidc_inst *inst,
struct v4l2_control *ctrl)
{

View file

@ -51,6 +51,8 @@
/* Maintains the number of FTB's between each FBD over a window */
#define DCVS_FTB_WINDOW 16
/* Superframe can have maximum of 32 frames */
#define VIDC_SUPERFRAME_MAX 32
#define V4L2_EVENT_VIDC_BASE 10
#define INPUT_MPLANE V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
@ -477,6 +479,7 @@ struct msm_vidc_inst {
struct msm_vidc_list etb_data;
struct msm_vidc_list fbd_data;
struct buffer_requirements buff_req;
struct vidc_frame_data superframe_data[VIDC_SUPERFRAME_MAX];
struct v4l2_ctrl_handler ctrl_handler;
struct completion completions[SESSION_MSG_END - SESSION_MSG_START + 1];
struct v4l2_ctrl **cluster;