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