@@ -1051,6 +1051,38 @@ static int delta_subscribe_event(struct v4l2_fh *fh,
return 0;
}
+
+static int delta_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct delta_ctx *ctx =
+ container_of(ctrl->handler, struct delta_ctx, ctrl_handler);
+ struct delta_dev *delta = ctx->dev;
+
+ switch (ctrl->id) {
+ case V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR:
+ break;
+ default:
+ dev_err(delta->dev, "%s unsupported control (%d)\n",
+ ctx->name, ctrl->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops delta_ctrl_ops = {
+ .s_ctrl = delta_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config delta_ctrl_mpeg2_meta = {
+ .ops = &delta_ctrl_ops,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR,
+ .type = V4L2_CTRL_TYPE_PRIVATE,
+ .name = "MPEG2 frame/slice metadata",
+ .max_reqs = VIDEO_MAX_FRAME,
+ .elem_size = sizeof(struct v4l2_ctrl_mpeg2_meta),
+};
+
/* v4l2 ioctl ops */
static const struct v4l2_ioctl_ops delta_ioctl_ops = {
.vidioc_querycap = delta_querycap,
@@ -1112,6 +1144,15 @@ static void delta_run_work(struct work_struct *work)
au->size = vb2_get_plane_payload(&vbuf->vb2_buf, 0);
au->dts = vbuf->vb2_buf.timestamp;
+ /* get access unit meta data */
+ ret = v4l2_ctrl_apply_request(&ctx->ctrl_handler, vbuf->request);
+ if (ret) {
+ dev_err(delta->dev, "%s failed to apply metadata control request (%d)\n",
+ ctx->name, ret);
+ goto out;
+ }
+ au->meta = ctx->meta_ctrl->p_new.p;
+
/* dump access unit */
dev_dbg(delta->dev, "%s dump %s", ctx->name,
dump_au(au, str, sizeof(str)));
@@ -1507,6 +1548,15 @@ static int delta_vb2_au_start_streaming(struct vb2_queue *q,
au->size = vb2_get_plane_payload(&vbuf->vb2_buf, 0);
au->dts = vbuf->vb2_buf.timestamp;
+ /* get access unit meta data */
+ ret = v4l2_ctrl_apply_request(&ctx->ctrl_handler, vbuf->request);
+ if (ret) {
+ dev_err(delta->dev, "%s failed to start streaming, cannot apply metadata control request (%d)\n",
+ ctx->name, ret);
+ goto err;
+ }
+ au->meta = ctx->meta_ctrl->p_new.p;
+
delta_push_dts(ctx, au->dts);
/* dump access unit */
@@ -1758,6 +1808,7 @@ static int queue_init(void *priv,
q->mem_ops = &vb2_dma_contig_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
q->lock = &delta->lock;
+ q->v4l2_allow_requests = true;
ret = vb2_queue_init(q);
if (ret)
return ret;
@@ -1778,6 +1829,33 @@ static int queue_init(void *priv,
return vb2_queue_init(q);
}
+static int delta_ctrls_setup(struct delta_ctx *ctx)
+{
+ struct delta_dev *delta = ctx->dev;
+ struct v4l2_ctrl_handler *hdl;
+
+ hdl = &ctx->ctrl_handler;
+ v4l2_ctrl_handler_init(hdl, 1);
+
+//FIXME, switch codec... so we can do this only when codec is known !
+ ctx->meta_ctrl = v4l2_ctrl_new_custom(hdl, &delta_ctrl_mpeg2_meta,
+ NULL);
+ ctx->meta_ctrl->flags |= V4L2_CTRL_FLAG_REQ_KEEP;
+
+ if (hdl->error) {
+ int err = hdl->error;
+
+ dev_err(delta->dev, "%s controls setup failed (%d)\n",
+ ctx->name, err);
+ v4l2_ctrl_handler_free(hdl);
+ return err;
+ }
+
+ v4l2_ctrl_handler_setup(hdl);
+
+ return 0;
+}
+
static int delta_open(struct file *file)
{
struct delta_dev *delta = video_drvdata(file);
@@ -1797,6 +1875,14 @@ static int delta_open(struct file *file)
file->private_data = &ctx->fh;
v4l2_fh_add(&ctx->fh);
+ ret = delta_ctrls_setup(ctx);
+ if (ret) {
+ dev_err(delta->dev, "%s failed to setup controls (%d)\n",
+ DELTA_PREFIX, ret);
+ goto err_fh_del;
+ }
+ ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+
INIT_WORK(&ctx->run_work, delta_run_work);
mutex_init(&ctx->lock);
@@ -1806,7 +1892,7 @@ static int delta_open(struct file *file)
ret = PTR_ERR(ctx->fh.m2m_ctx);
dev_err(delta->dev, "%s failed to initialize m2m context (%d)\n",
DELTA_PREFIX, ret);
- goto err_fh_del;
+ goto err_ctrls;
}
/* wait stream format to determine which
@@ -1840,6 +1926,8 @@ static int delta_open(struct file *file)
return 0;
+err_ctrls:
+ v4l2_ctrl_handler_free(&ctx->ctrl_handler);
err_fh_del:
v4l2_fh_del(&ctx->fh);
v4l2_fh_exit(&ctx->fh);
@@ -1871,6 +1959,8 @@ static int delta_release(struct file *file)
v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+ v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+
v4l2_fh_del(&ctx->fh);
v4l2_fh_exit(&ctx->fh);
@@ -8,6 +8,7 @@
#define DELTA_H
#include <linux/rpmsg.h>
+#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mem2mem.h>
@@ -106,6 +107,7 @@ struct delta_au {
dma_addr_t paddr;
__u32 flags;
u64 dts;
+ void *meta;
};
/*
@@ -401,6 +403,8 @@ struct delta_dev;
*
* @flags: validity of fields (streaminfo)
* @fh: V4L2 file handle
+ * @ctrl_handler: V4L2 controls handler
+ * @meta_ctrl: access unit meta data control
* @dev: device context
* @dec: selected decoder context for this instance
* @ipc_ctx: context of IPC communication with firmware
@@ -433,10 +437,11 @@ struct delta_dev;
struct delta_ctx {
__u32 flags;
struct v4l2_fh fh;
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl *meta_ctrl;
struct delta_dev *dev;
const struct delta_dec *dec;
struct delta_ipc_ctx ipc_ctx;
-
enum delta_state state;
u32 frame_num;
u32 au_num;
@@ -456,6 +461,7 @@ struct delta_ctx {
struct work_struct run_work;
struct mutex lock;
bool aborting;
+ struct v4l2_ctrl_handler hdl;
void *priv;
};