video: driver: enable encoder superframe batching support

Added HFR/HSR superframe handling support for encoder.

Change-Id: I28ced3f223cd78d00b1a654a79bcac3b02f378dc
Signed-off-by: Govindaraj Rajagopal <grajagop@codeaurora.org>
This commit is contained in:
Govindaraj Rajagopal
2021-02-16 21:11:21 +05:30
parent 6070bc2523
commit f02bbaf836
10 changed files with 207 additions and 3 deletions

View File

@@ -239,6 +239,11 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
HFI_PROP_ROTATION, HFI_PROP_ROTATION,
CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT}, CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT},
{SUPER_FRAME, ENC, CODECS_ALL,
0, 16, 1, 0,
V4L2_CID_MPEG_VIDC_SUPERFRAME,
0},
{SLICE_INTERFACE, DEC, CODECS_ALL, {SLICE_INTERFACE, DEC, CODECS_ALL,
0, 0, 0, 0, 0, 0, 0, 0,
V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE,

View File

@@ -302,5 +302,6 @@ void inst_unlock(struct msm_vidc_inst *inst, const char *function);
bool inst_lock_check(struct msm_vidc_inst *inst, const char *function); bool inst_lock_check(struct msm_vidc_inst *inst, const char *function);
int msm_vidc_update_meta_port_settings(struct msm_vidc_inst *inst); int msm_vidc_update_meta_port_settings(struct msm_vidc_inst *inst);
void msm_vidc_schedule_core_deinit(struct msm_vidc_core *core); void msm_vidc_schedule_core_deinit(struct msm_vidc_core *core);
bool msm_vidc_is_super_buffer(struct msm_vidc_inst *inst);
#endif // _MSM_VIDC_DRIVER_H_ #endif // _MSM_VIDC_DRIVER_H_

View File

@@ -43,7 +43,8 @@
#define MAX_CAP_CHILDREN 16 #define MAX_CAP_CHILDREN 16
#define DEFAULT_BITSTREM_ALIGNMENT 16 #define DEFAULT_BITSTREM_ALIGNMENT 16
#define H265_BITSTREM_ALIGNMENT 32 #define H265_BITSTREM_ALIGNMENT 32
#define DEFAULT_MAX_HOST_BUF_COUNT 32 #define DEFAULT_MAX_HOST_ENC_BUF_COUNT 64
#define DEFAULT_MAX_HOST_DEC_BUF_COUNT 64
#define BIT_DEPTH_8 (8 << 16 | 8) #define BIT_DEPTH_8 (8 << 16 | 8)
#define BIT_DEPTH_10 (10 << 16 | 10) #define BIT_DEPTH_10 (10 << 16 | 10)
#define CODED_FRAMES_MBS_ONLY HFI_BITMASK_FRAME_MBS_ONLY_FLAG #define CODED_FRAMES_MBS_ONLY HFI_BITMASK_FRAME_MBS_ONLY_FLAG
@@ -266,6 +267,7 @@ enum msm_vidc_inst_capability_type {
HFLIP, HFLIP,
VFLIP, VFLIP,
ROTATION, ROTATION,
SUPER_FRAME,
SLICE_INTERFACE, SLICE_INTERFACE,
HEADER_MODE, HEADER_MODE,
PREPEND_SPSPPS_TO_IDR, PREPEND_SPSPPS_TO_IDR,

View File

@@ -35,6 +35,8 @@ int venus_hfi_session_command(struct msm_vidc_inst *inst,
void *payload, u32 payload_size); void *payload, u32 payload_size);
int venus_hfi_queue_buffer(struct msm_vidc_inst *inst, int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buffer, struct msm_vidc_buffer *metabuf); struct msm_vidc_buffer *buffer, struct msm_vidc_buffer *metabuf);
int venus_hfi_queue_super_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buffer, struct msm_vidc_buffer *metabuf);
int venus_hfi_release_buffer(struct msm_vidc_inst *inst, int venus_hfi_release_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buffer); struct msm_vidc_buffer *buffer);
int venus_hfi_start(struct msm_vidc_inst *inst, enum msm_vidc_port_type port); int venus_hfi_start(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);

View File

@@ -244,7 +244,7 @@ static int msm_venc_set_host_max_buf_count(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port) enum msm_vidc_port_type port)
{ {
int rc = 0; int rc = 0;
u32 count = DEFAULT_MAX_HOST_BUF_COUNT; u32 count = DEFAULT_MAX_HOST_ENC_BUF_COUNT;
if (port != INPUT_PORT && port != OUTPUT_PORT) { if (port != INPUT_PORT && port != OUTPUT_PORT) {
i_vpr_e(inst, "%s: invalid port %d\n", __func__, port); i_vpr_e(inst, "%s: invalid port %d\n", __func__, port);

View File

@@ -204,6 +204,8 @@ static const char *msm_vidc_get_priv_ctrl_name(struct msm_vidc_inst *inst, u32 c
return "HEVC I Frame Max QP"; return "HEVC I Frame Max QP";
case V4L2_CID_MPEG_VIDC_HEVC_P_FRAME_MAX_QP: case V4L2_CID_MPEG_VIDC_HEVC_P_FRAME_MAX_QP:
return "HEVC P Frame Max QP"; return "HEVC P Frame Max QP";
case V4L2_CID_MPEG_VIDC_SUPERFRAME:
return "Encoder Batching Superframe";
default: default:
i_vpr_e(inst, "%s: ctrl name not available for ctrl id %#x\n", i_vpr_e(inst, "%s: ctrl name not available for ctrl id %#x\n",
__func__, control_id); __func__, control_id);

View File

@@ -1438,6 +1438,20 @@ struct msm_vidc_buffer *get_meta_buffer(struct msm_vidc_inst *inst,
return mbuf; return mbuf;
} }
bool msm_vidc_is_super_buffer(struct msm_vidc_inst *inst)
{
struct msm_vidc_inst_capability *capability = NULL;
if (!inst || !inst->capabilities) {
i_vpr_e(inst, "%s: Invalid params\n", __func__);
return false;
}
capability = inst->capabilities;
return !!capability->cap[SUPER_FRAME].value;
}
int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
{ {
int rc = 0; int rc = 0;
@@ -1492,6 +1506,9 @@ int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
return -EINVAL; return -EINVAL;
} }
} }
if (msm_vidc_is_super_buffer(inst) && is_input_buffer(buf->type))
rc = venus_hfi_queue_super_buffer(inst, buf, meta);
else
rc = venus_hfi_queue_buffer(inst, buf, meta); rc = venus_hfi_queue_buffer(inst, buf, meta);
if (rc) if (rc)
return rc; return rc;

View File

@@ -33,6 +33,14 @@
#define MAX_FIRMWARE_NAME_SIZE 128 #define MAX_FIRMWARE_NAME_SIZE 128
#define update_offset(offset, val) ((offset) += (val))
#define update_timestamp(ts, val) \
do { \
do_div((ts), NSEC_PER_USEC); \
(ts) += (val); \
(ts) *= NSEC_PER_USEC; \
} while (0)
extern struct msm_vidc_core *g_core; extern struct msm_vidc_core *g_core;
static int __resume(struct msm_vidc_core *core); static int __resume(struct msm_vidc_core *core);
@@ -879,6 +887,18 @@ int __iface_cmdq_write(struct msm_vidc_core *core,
return rc; return rc;
} }
static int __iface_cmdq_write_intr(struct msm_vidc_core *core,
void *pkt, bool allow)
{
bool needs_interrupt = false;
int rc = __iface_cmdq_write_relaxed(core, pkt, &needs_interrupt);
if (!rc && allow && needs_interrupt)
call_venus_op(core, raise_interrupt, core);
return rc;
}
int __iface_msgq_read(struct msm_vidc_core *core, void *pkt) int __iface_msgq_read(struct msm_vidc_core *core, void *pkt)
{ {
u32 tx_req_is_set = 0; u32 tx_req_is_set = 0;
@@ -3024,6 +3044,125 @@ unlock:
return rc; return rc;
} }
int venus_hfi_queue_super_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buffer, struct msm_vidc_buffer *metabuf)
{
int rc = 0;
struct msm_vidc_core *core;
struct hfi_buffer hfi_buffer;
struct hfi_buffer hfi_meta_buffer;
struct msm_vidc_inst_capability *capability;
u32 frame_size, meta_size, batch_size, cnt = 0;
u64 ts_delta_us;
if (!inst || !inst->core || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
capability = inst->capabilities;
core_lock(core, __func__);
if (!__valdiate_session(core, inst, __func__)) {
rc = -EINVAL;
goto unlock;
}
/* Get super yuv buffer */
rc = get_hfi_buffer(inst, buffer, &hfi_buffer);
if (rc)
goto unlock;
/* Get super meta buffer */
if (metabuf) {
rc = get_hfi_buffer(inst, metabuf, &hfi_meta_buffer);
if (rc)
goto unlock;
}
batch_size = capability->cap[SUPER_FRAME].value;
frame_size = call_session_op(core, buffer_size, inst, MSM_VIDC_BUF_INPUT);
meta_size = call_session_op(core, buffer_size, inst, MSM_VIDC_BUF_INPUT_META);
ts_delta_us = 1000000 / (capability->cap[FRAME_RATE].value >> 16);
/* Sanitize super yuv buffer */
if (frame_size * batch_size != buffer->buffer_size) {
i_vpr_e(inst, "%s: invalid super yuv buffer. frame %u, batch %u, buffer size %u\n",
__func__, frame_size, batch_size, buffer->buffer_size);
goto unlock;
}
/* Sanitize super meta buffer */
if (metabuf && meta_size * batch_size != metabuf->buffer_size) {
i_vpr_e(inst, "%s: invalid super meta buffer. meta %u, batch %u, buffer size %u\n",
__func__, meta_size, batch_size, metabuf->buffer_size);
goto unlock;
}
/* Initialize yuv buffer */
hfi_buffer.data_size = frame_size;
hfi_buffer.addr_offset = 0;
/* Initialize meta buffer */
if (metabuf) {
hfi_meta_buffer.data_size = meta_size;
hfi_meta_buffer.addr_offset = 0;
}
while (cnt < batch_size) {
/* Create header */
rc = hfi_create_header(inst->packet, inst->packet_size,
inst->session_id, core->header_id++);
if (rc)
goto unlock;
/* Create yuv packet */
update_offset(hfi_buffer.addr_offset, (cnt ? frame_size : 0u));
update_timestamp(hfi_buffer.timestamp, (cnt ? ts_delta_us : 0u));
rc = hfi_create_packet(inst->packet,
inst->packet_size,
HFI_CMD_BUFFER,
HFI_HOST_FLAGS_INTR_REQUIRED,
HFI_PAYLOAD_STRUCTURE,
get_hfi_port_from_buffer_type(inst, buffer->type),
core->packet_id++,
&hfi_buffer,
sizeof(hfi_buffer));
if (rc)
goto unlock;
/* Create meta packet */
if (metabuf) {
update_offset(hfi_meta_buffer.addr_offset, (cnt ? meta_size : 0u));
update_timestamp(hfi_meta_buffer.timestamp, (cnt ? ts_delta_us : 0u));
rc = hfi_create_packet(inst->packet,
inst->packet_size,
HFI_CMD_BUFFER,
HFI_HOST_FLAGS_INTR_REQUIRED,
HFI_PAYLOAD_STRUCTURE,
get_hfi_port_from_buffer_type(inst, metabuf->type),
core->packet_id++,
&hfi_meta_buffer,
sizeof(hfi_meta_buffer));
if (rc)
goto unlock;
}
/* Raise interrupt only for last pkt in the batch */
rc = __iface_cmdq_write_intr(inst->core, inst->packet, (cnt == batch_size - 1));
if (rc)
goto unlock;
cnt++;
}
unlock:
core_unlock(core, __func__);
if (rc)
i_vpr_e(inst, "%s: queue super buffer failed: %d\n", __func__, rc);
return rc;
}
int venus_hfi_queue_buffer(struct msm_vidc_inst *inst, int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buffer, struct msm_vidc_buffer *metabuf) struct msm_vidc_buffer *buffer, struct msm_vidc_buffer *metabuf)
{ {

View File

@@ -440,8 +440,15 @@ static int handle_input_buffer(struct msm_vidc_inst *inst,
int rc = 0; int rc = 0;
struct msm_vidc_buffers *buffers; struct msm_vidc_buffers *buffers;
struct msm_vidc_buffer *buf; struct msm_vidc_buffer *buf;
struct msm_vidc_core *core;
u32 frame_size, batch_size;
bool found; bool found;
if (!inst || !buffer || !inst->capabilities || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_INPUT, __func__); buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_INPUT, __func__);
if (!buffers) if (!buffers)
return -EINVAL; return -EINVAL;
@@ -458,6 +465,16 @@ static int handle_input_buffer(struct msm_vidc_inst *inst,
__func__, buffer->index, buffer->base_address); __func__, buffer->index, buffer->base_address);
return -EINVAL; return -EINVAL;
} }
frame_size = call_session_op(core, buffer_size, inst, MSM_VIDC_BUF_INPUT);
batch_size = inst->capabilities->cap[SUPER_FRAME].value;
/* attach dequeued flag for, only last frame in the batch */
if (msm_vidc_is_super_buffer(inst) &&
buffer->addr_offset / frame_size < batch_size - 1) {
i_vpr_h(inst, "%s: superframe last buffer not reached: %u, %u, %u\n",
__func__, buffer->addr_offset, frame_size, batch_size);
return 0;
}
buf->data_offset = buffer->data_offset; buf->data_offset = buffer->data_offset;
buf->data_size = buffer->data_size; buf->data_size = buffer->data_size;
buf->attr &= ~MSM_VIDC_ATTR_QUEUED; buf->attr &= ~MSM_VIDC_ATTR_QUEUED;
@@ -549,8 +566,15 @@ static int handle_input_metadata_buffer(struct msm_vidc_inst *inst,
int rc = 0; int rc = 0;
struct msm_vidc_buffers *buffers; struct msm_vidc_buffers *buffers;
struct msm_vidc_buffer *buf; struct msm_vidc_buffer *buf;
struct msm_vidc_core *core;
u32 frame_size, batch_size;
bool found; bool found;
if (!inst || !buffer || !inst->capabilities || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_INPUT_META, __func__); buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_INPUT_META, __func__);
if (!buffers) if (!buffers)
return -EINVAL; return -EINVAL;
@@ -567,6 +591,15 @@ static int handle_input_metadata_buffer(struct msm_vidc_inst *inst,
__func__, buffer->index, buffer->base_address); __func__, buffer->index, buffer->base_address);
return -EINVAL; return -EINVAL;
} }
frame_size = call_session_op(core, buffer_size, inst, MSM_VIDC_BUF_INPUT_META);
batch_size = inst->capabilities->cap[SUPER_FRAME].value;
/* attach dequeued flag for, only last frame in the batch */
if (msm_vidc_is_super_buffer(inst) &&
buffer->addr_offset / frame_size < batch_size - 1) {
i_vpr_h(inst, "%s: superframe last buffer not reached: %u, %u, %u\n",
__func__, buffer->addr_offset, frame_size, batch_size);
return 0;
}
buf->data_size = buffer->data_size; buf->data_size = buffer->data_size;
buf->attr &= ~MSM_VIDC_ATTR_QUEUED; buf->attr &= ~MSM_VIDC_ATTR_QUEUED;
buf->attr |= MSM_VIDC_ATTR_DEQUEUED; buf->attr |= MSM_VIDC_ATTR_DEQUEUED;

View File

@@ -116,6 +116,9 @@ enum v4l2_mpeg_vidc_blur_types {
#define V4L2_CID_MPEG_VIDC_HEVC_P_FRAME_MAX_QP \ #define V4L2_CID_MPEG_VIDC_HEVC_P_FRAME_MAX_QP \
(V4L2_CID_MPEG_VIDC_BASE + 0x27) (V4L2_CID_MPEG_VIDC_BASE + 0x27)
/* Encoder Super frame control */
#define V4L2_CID_MPEG_VIDC_SUPERFRAME (V4L2_CID_MPEG_VIDC_BASE + 0x28)
enum v4l2_mpeg_vidc_metapayload_header_flags { enum v4l2_mpeg_vidc_metapayload_header_flags {
METADATA_FLAGS_NONE = 0, METADATA_FLAGS_NONE = 0,
METADATA_FLAGS_TOP_FIELD = (1 << 0), METADATA_FLAGS_TOP_FIELD = (1 << 0),