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,
|
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,
|
||||||
|
@@ -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_
|
||||||
|
|
||||||
|
@@ -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,
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -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)
|
||||||
{
|
{
|
||||||
|
@@ -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;
|
||||||
|
@@ -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),
|
||||||
|
Reference in New Issue
Block a user