[RFC PATCH 2/3] Enable Request API for output buffers

From: Dikshita Agarwal
Date: Fri May 08 2020 - 02:23:10 EST


Change-Id: Ic09179f503bf7d4bb41522fb70207728405cc7b3
Signed-off-by: Dikshita Agarwal <dikshita@xxxxxxxxxxxxxx>
---
drivers/media/platform/Kconfig | 2 +-
drivers/media/platform/qcom/venus/core.h | 3 ++
drivers/media/platform/qcom/venus/helpers.c | 75 +++++++++++++++++++++++++-
drivers/media/platform/qcom/venus/venc.c | 25 ++++++++-
drivers/media/platform/qcom/venus/venc_ctrls.c | 61 ++++++++++++++++++++-
drivers/media/v4l2-core/v4l2-ctrls.c | 10 ++++
include/media/v4l2-ctrls.h | 1 +
include/media/venus-ctrls.h | 22 ++++++++
8 files changed, 195 insertions(+), 4 deletions(-)
create mode 100644 include/media/venus-ctrls.h

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index a51f76e..064b57b 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -481,7 +481,7 @@ config VIDEO_TI_VPE_DEBUG

config VIDEO_QCOM_VENUS
tristate "Qualcomm Venus V4L2 encoder/decoder driver"
- depends on VIDEO_DEV && VIDEO_V4L2 && MEDIA_CONTROLLER
+ depends on VIDEO_DEV && VIDEO_V4L2 && MEDIA_CONTROLLER && MEDIA_CONTROLLER_REQUEST_API
depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST
select QCOM_MDT_LOADER if ARCH_QCOM
select QCOM_SCM if ARCH_QCOM
diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
index 91ff08d..9535d33 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -11,6 +11,8 @@
#include <media/videobuf2-v4l2.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
+#include <linux/time.h>
+#include <linux/timer.h>

#include "hfi.h"

@@ -320,6 +322,7 @@ struct venus_ts_metadata {
struct venus_inst {
struct list_head list;
struct mutex lock;
+ struct mutex req_lock;
struct venus_core *core;
struct list_head dpbbufs;
struct list_head internalbufs;
diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c
index 2c766cd..c966c24 100644
--- a/drivers/media/platform/qcom/venus/helpers.c
+++ b/drivers/media/platform/qcom/venus/helpers.c
@@ -27,6 +27,63 @@ struct intbuf {
unsigned long attrs;
};

+int venus_ctrl_request_process(struct media_request *req)
+{
+ struct v4l2_ext_control control;
+ struct v4l2_ext_controls controls;
+ int ret = 0;
+ //struct media_device mdev = inst->core->m_dev;
+
+ struct media_request_object *obj;
+ struct v4l2_ctrl_handler *parent_hdl, *hdl;
+ struct venus_inst *inst;
+ struct v4l2_ctrl *ctrl;
+ struct v4l2_ctrl_ref *ref;
+ unsigned int count;
+ list_for_each_entry(obj, &req->objects, list) {
+ struct vb2_buffer *vb;
+
+ if (vb2_request_object_is_buffer(obj)) {
+ vb = container_of(obj, struct vb2_buffer, req_obj);
+ inst = vb2_get_drv_priv(vb->vb2_queue);
+ //struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
+ break;
+ }
+ }
+
+ if (!inst) {
+ pr_debug("No buffer was provided with the request\n");
+ return -ENOENT;
+ }
+ struct video_device *vdev = inst->core->vdev_enc;
+ count = vb2_request_buffer_cnt(req);
+ if (!count) {
+ pr_debug("No buffer was provided with the request\n");
+ return -ENOENT;
+ } else if (count > 1) {
+ pr_debug("More than one buffer was provided with the request\n");
+ return -EINVAL;
+ }
+
+ parent_hdl = &inst->ctrl_handler;
+
+ hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl);
+ if (!hdl) {
+ pr_debug( "Missing control handler\n");
+ return -ENOENT;
+ }
+
+ ctrl = v4l2_ctrl_request_hdl_ctrl_find(hdl,
+ V4L2_CID_MPEG_VIDEO_VENUS_METADATA);
+
+ pr_debug("venus_ctrl_request_process ctrl id %d index %d",ctrl->id,ctrl->p_new.p_metadata->index);
+ return ret;
+}
+
+static int venus_helper_register_entity(struct media_device *mdev,
+ struct venus_media *media, enum venus_helper_entity_type type,
+ struct video_device *vdev, int function);
+
bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt)
{
struct venus_core *core = inst->core;
@@ -522,7 +579,10 @@ void venus_helper_get_ts_metadata(struct venus_inst *inst, u64 timestamp_us,
unsigned int type = vb->type;
struct hfi_frame_data fdata;
int ret;
-
+ struct media_request *req;
+ u64 ts,ts_ms;
+ struct timespec tv;
+ req = vb->req_obj.req;
memset(&fdata, 0, sizeof(fdata));
fdata.alloc_len = buf->size;
fdata.device_addr = buf->dma_addr;
@@ -549,7 +609,20 @@ void venus_helper_get_ts_metadata(struct venus_inst *inst, u64 timestamp_us,
fdata.filled_len = 0;
fdata.offset = 0;
}
+ if(req && type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ {
+ ret = v4l2_ctrl_request_setup(req, &inst->ctrl_handler);
+ if (ret)
+ pr_debug("v4l2_ctrl_request_setup retunred error");
+ ret = venus_ctrl_request_process(req);
+ }

+ pr_debug("buf type %d buf index %d",fdata.buffer_type,vbuf->vb2_buf.index);
+ if(type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ getnstimeofday(&tv);
+ ts = (tv.tv_sec * 1000000) + (tv.tv_nsec / 1000);
+ pr_debug("ETB: BUF %d queued at tv sec %ld ts ns %ld ts usec %lld",vbuf->vb2_buf.index,tv.tv_sec,tv.tv_nsec,ts);
+ }
ret = hfi_session_process_buf(inst, &fdata);
if (ret)
return ret;
diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index f57542f..599cfae 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -1031,6 +1031,21 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
return ret;
}

+static int venc_buf_out_validate(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+ vbuf->field = V4L2_FIELD_NONE;
+ return 0;
+}
+
+static void venc_buf_request_complete(struct vb2_buffer *vb)
+{
+ struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
+
+ v4l2_ctrl_request_complete(vb->req_obj.req, &inst->ctrl_handler);
+}
+
static const struct vb2_ops venc_vb2_ops = {
.queue_setup = venc_queue_setup,
.buf_init = venus_helper_vb2_buf_init,
@@ -1038,6 +1053,8 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
.start_streaming = venc_start_streaming,
.stop_streaming = venus_helper_vb2_stop_streaming,
.buf_queue = venus_helper_vb2_buf_queue,
+ .buf_out_validate = venc_buf_out_validate,
+ .buf_request_complete = venc_buf_request_complete,
};

static void venc_buf_done(struct venus_inst *inst, unsigned int buf_type,
@@ -1068,7 +1085,8 @@ static void venc_buf_done(struct venus_inst *inst, unsigned int buf_type,
} else {
vbuf->sequence = inst->sequence_out++;
}
-
+ if (buf_type == HFI_BUFFER_INPUT)
+ v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, &inst->ctrl_handler);
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
}

@@ -1109,6 +1127,9 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->allow_zero_bytesused = 1;
src_vq->min_buffers_needed = 1;
src_vq->dev = inst->core->dev;
+ src_vq->supports_requests = 1;
+ src_vq->requires_requests = 1;
+ src_vq->lock = &inst->req_lock;
if (inst->core->res->hfi_version == HFI_VERSION_1XX)
src_vq->bidirectional = 1;
ret = vb2_queue_init(src_vq);
@@ -1125,6 +1146,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->allow_zero_bytesused = 1;
dst_vq->min_buffers_needed = 1;
dst_vq->dev = inst->core->dev;
+ dst_vq->lock = src_vq->lock;
ret = vb2_queue_init(dst_vq);
if (ret) {
vb2_queue_release(src_vq);
@@ -1163,6 +1185,7 @@ static int venc_open(struct file *file)
INIT_LIST_HEAD(&inst->internalbufs);
INIT_LIST_HEAD(&inst->list);
mutex_init(&inst->lock);
+ mutex_init(&inst->req_lock);

inst->core = core;
inst->session_type = VIDC_SESSION_TYPE_ENC;
diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c
index 877c0b3..02921b5 100644
--- a/drivers/media/platform/qcom/venus/venc_ctrls.c
+++ b/drivers/media/platform/qcom/venus/venc_ctrls.c
@@ -199,6 +199,12 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
}
mutex_unlock(&inst->lock);
break;
+ case V4L2_CID_MPEG_VIDEO_VENUS_METADATA: {
+ unsigned int i;
+ const struct v4l2_ctrl_venus_metadata *metadata = ctrl->p_new.p_metadata;
+ pr_debug("%s: VENUS_METADATA p_new set index %d \n", __func__,metadata->index);
+ break;
+ }
default:
return -EINVAL;
}
@@ -206,15 +212,66 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
}

+static int venc_op_try_ctrl(struct v4l2_ctrl *ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_MPEG_VIDEO_VENUS_METADATA: {
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+static void meta_type_init(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr)
+{
+}
+
+static bool meta_type_equal(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr1,
+ union v4l2_ctrl_ptr ptr2)
+{
+ return true;
+}
+
+static void meta_type_log(const struct v4l2_ctrl *ctrl)
+{
+}
+
+static int meta_type_validate(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr)
+{
+ return 0;
+}
+
static const struct v4l2_ctrl_ops venc_ctrl_ops = {
.s_ctrl = venc_op_s_ctrl,
+ .try_ctrl = venc_op_try_ctrl,
+};
+
+static const struct v4l2_ctrl_type_ops venus_meta_type_ops = {
+ .equal = meta_type_equal,
+ .init = meta_type_init,
+ .log = meta_type_log,
+ .validate = meta_type_validate,
+};
+
+static const struct v4l2_ctrl_config venus_meta_cfg = {
+ .name = "Venus codec metadata",
+ .type = V4L2_CTRL_TYPE_VENUS_METADATA,
+ .ops = &venc_ctrl_ops,
+ .id = V4L2_CID_MPEG_VIDEO_VENUS_METADATA,
+ .flags = V4L2_CTRL_FLAG_EXECUTE_ON_WRITE,
+ .elem_size = sizeof(struct v4l2_ctrl_venus_metadata),
+ .type_ops = &venus_meta_type_ops,
};

int venc_ctrl_init(struct venus_inst *inst)
{
int ret;

- ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 30);
+ ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 30+1);
if (ret)
return ret;

@@ -351,6 +408,8 @@ int venc_ctrl_init(struct venus_inst *inst)
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME, 0, 0, 0, 0);

+ v4l2_ctrl_new_custom(&inst->ctrl_handler, &venus_meta_cfg, NULL);
+
ret = inst->ctrl_handler.error;
if (ret)
goto err;
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index cd84dbb..9f7f024 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -892,6 +892,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS: return "MPEG-2 Slice Parameters";
case V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION: return "MPEG-2 Quantization Matrices";
case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS: return "FWHT Stateless Parameters";
+ case V4L2_CID_MPEG_VIDEO_VENUS_METADATA: return "Venus codec metadata";
case V4L2_CID_FWHT_I_FRAME_QP: return "FWHT I-Frame QP Value";
case V4L2_CID_FWHT_P_FRAME_QP: return "FWHT P-Frame QP Value";

@@ -1357,6 +1358,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS:
*type = V4L2_CTRL_TYPE_FWHT_PARAMS;
break;
+ case V4L2_CID_MPEG_VIDEO_VENUS_METADATA:
+ *type = V4L2_CTRL_TYPE_VENUS_METADATA;
+ break;
case V4L2_CID_MPEG_VIDEO_H264_SPS:
*type = V4L2_CTRL_TYPE_H264_SPS;
break;
@@ -1820,6 +1824,9 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
return -ERANGE;
return 0;

+ case V4L2_CTRL_TYPE_VENUS_METADATA:
+ return 0;
+
default:
return std_validate_compound(ctrl, idx, ptr);
}
@@ -2403,6 +2410,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
case V4L2_CTRL_TYPE_FWHT_PARAMS:
elem_size = sizeof(struct v4l2_ctrl_fwht_params);
break;
+ case V4L2_CTRL_TYPE_VENUS_METADATA:
+ elem_size = sizeof(struct v4l2_ctrl_venus_metadata);
+ break;
case V4L2_CTRL_TYPE_H264_SPS:
elem_size = sizeof(struct v4l2_ctrl_h264_sps);
break;
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 570ff4b..c66b797 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -12,6 +12,7 @@
#include <linux/mutex.h>
#include <linux/videodev2.h>
#include <media/media-request.h>
+#include <media/venus-ctrls.h>

/*
* Include the stateless codec compound control definitions.
diff --git a/include/media/venus-ctrls.h b/include/media/venus-ctrls.h
new file mode 100644
index 0000000..9179ef0
--- /dev/null
+++ b/include/media/venus-ctrls.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+Copyright (c) 2020, The Linux Foundation. All rights reserved. */
+/*
+ * These are custom (compound) controls for Venus codec driver.
+ *
+ * It turns out that these structs are not stable yet and will undergo
+ * more changes. So keep them private until they are stable and ready to
+ * become part of the official public API.
+ */
+
+#ifndef _VENUS_CTRLS_H_
+#define _VENUS_CTRLS_H_
+
+#define V4L2_CTRL_TYPE_VENUS_METADATA 0x0107
+#define V4L2_CID_MPEG_VIDEO_VENUS_METADATA (V4L2_CID_MPEG_BASE + 293)
+
+struct v4l2_ctrl_venus_metadata {
+ unsigned int index;
+// __u8 rawdata[16];
+};
+
+#endif
\ No newline at end of file
--
1.9.1