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:
@@ -239,6 +239,11 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
|
||||
HFI_PROP_ROTATION,
|
||||
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,
|
||||
0, 0, 0, 0,
|
||||
V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE,
|
||||
|
@@ -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);
|
||||
int msm_vidc_update_meta_port_settings(struct msm_vidc_inst *inst);
|
||||
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_
|
||||
|
||||
|
@@ -43,7 +43,8 @@
|
||||
#define MAX_CAP_CHILDREN 16
|
||||
#define DEFAULT_BITSTREM_ALIGNMENT 16
|
||||
#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_10 (10 << 16 | 10)
|
||||
#define CODED_FRAMES_MBS_ONLY HFI_BITMASK_FRAME_MBS_ONLY_FLAG
|
||||
@@ -266,6 +267,7 @@ enum msm_vidc_inst_capability_type {
|
||||
HFLIP,
|
||||
VFLIP,
|
||||
ROTATION,
|
||||
SUPER_FRAME,
|
||||
SLICE_INTERFACE,
|
||||
HEADER_MODE,
|
||||
PREPEND_SPSPPS_TO_IDR,
|
||||
|
@@ -35,6 +35,8 @@ int venus_hfi_session_command(struct msm_vidc_inst *inst,
|
||||
void *payload, u32 payload_size);
|
||||
int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
|
||||
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,
|
||||
struct msm_vidc_buffer *buffer);
|
||||
int venus_hfi_start(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
|
||||
|
@@ -244,7 +244,7 @@ static int msm_venc_set_host_max_buf_count(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_port_type port)
|
||||
{
|
||||
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) {
|
||||
i_vpr_e(inst, "%s: invalid port %d\n", __func__, port);
|
||||
|
@@ -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";
|
||||
case V4L2_CID_MPEG_VIDC_HEVC_P_FRAME_MAX_QP:
|
||||
return "HEVC P Frame Max QP";
|
||||
case V4L2_CID_MPEG_VIDC_SUPERFRAME:
|
||||
return "Encoder Batching Superframe";
|
||||
default:
|
||||
i_vpr_e(inst, "%s: ctrl name not available for ctrl id %#x\n",
|
||||
__func__, control_id);
|
||||
|
@@ -1438,6 +1438,20 @@ struct msm_vidc_buffer *get_meta_buffer(struct msm_vidc_inst *inst,
|
||||
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 rc = 0;
|
||||
@@ -1492,6 +1506,9 @@ int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
|
||||
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);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
@@ -33,6 +33,14 @@
|
||||
|
||||
#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;
|
||||
|
||||
static int __resume(struct msm_vidc_core *core);
|
||||
@@ -879,6 +887,18 @@ int __iface_cmdq_write(struct msm_vidc_core *core,
|
||||
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)
|
||||
{
|
||||
u32 tx_req_is_set = 0;
|
||||
@@ -3024,6 +3044,125 @@ unlock:
|
||||
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,
|
||||
struct msm_vidc_buffer *buffer, struct msm_vidc_buffer *metabuf)
|
||||
{
|
||||
|
@@ -440,8 +440,15 @@ static int handle_input_buffer(struct msm_vidc_inst *inst,
|
||||
int rc = 0;
|
||||
struct msm_vidc_buffers *buffers;
|
||||
struct msm_vidc_buffer *buf;
|
||||
struct msm_vidc_core *core;
|
||||
u32 frame_size, batch_size;
|
||||
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__);
|
||||
if (!buffers)
|
||||
return -EINVAL;
|
||||
@@ -458,6 +465,16 @@ static int handle_input_buffer(struct msm_vidc_inst *inst,
|
||||
__func__, buffer->index, buffer->base_address);
|
||||
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_size = buffer->data_size;
|
||||
buf->attr &= ~MSM_VIDC_ATTR_QUEUED;
|
||||
@@ -549,8 +566,15 @@ static int handle_input_metadata_buffer(struct msm_vidc_inst *inst,
|
||||
int rc = 0;
|
||||
struct msm_vidc_buffers *buffers;
|
||||
struct msm_vidc_buffer *buf;
|
||||
struct msm_vidc_core *core;
|
||||
u32 frame_size, batch_size;
|
||||
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__);
|
||||
if (!buffers)
|
||||
return -EINVAL;
|
||||
@@ -567,6 +591,15 @@ static int handle_input_metadata_buffer(struct msm_vidc_inst *inst,
|
||||
__func__, buffer->index, buffer->base_address);
|
||||
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->attr &= ~MSM_VIDC_ATTR_QUEUED;
|
||||
buf->attr |= MSM_VIDC_ATTR_DEQUEUED;
|
||||
|
@@ -116,6 +116,9 @@ enum v4l2_mpeg_vidc_blur_types {
|
||||
#define V4L2_CID_MPEG_VIDC_HEVC_P_FRAME_MAX_QP \
|
||||
(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 {
|
||||
METADATA_FLAGS_NONE = 0,
|
||||
METADATA_FLAGS_TOP_FIELD = (1 << 0),
|
||||
|
Reference in New Issue
Block a user