From: Dafna Hirschfeld <dafna3@gmail.com>
To: linux-media@vger.kernel.org
Cc: hverkuil@xs4all.nl, helen.koike@collabora.com,
Dafna Hirschfeld <dafna3@gmail.com>
Subject: [PATCH 9/9] media: vicodec: Add support for stateless decoder.
Date: Sat, 9 Feb 2019 05:54:27 -0800 [thread overview]
Message-ID: <20190209135427.20630-10-dafna3@gmail.com> (raw)
In-Reply-To: <20190209135427.20630-1-dafna3@gmail.com>
Implement a stateless decoder for the new node.
Signed-off-by: Dafna Hirschfeld <dafna3@gmail.com>
---
drivers/media/platform/vicodec/vicodec-core.c | 202 ++++++++++++++++--
1 file changed, 190 insertions(+), 12 deletions(-)
diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c
index 9a6ee593ae19..9fda0f9138e8 100644
--- a/drivers/media/platform/vicodec/vicodec-core.c
+++ b/drivers/media/platform/vicodec/vicodec-core.c
@@ -117,6 +117,7 @@ struct vicodec_ctx {
bool is_enc;
bool is_stateless;
spinlock_t *lock;
+ struct media_request *cur_req;
struct v4l2_ctrl_handler hdl;
@@ -136,6 +137,7 @@ struct vicodec_ctx {
bool comp_has_next_frame;
bool first_source_change_sent;
bool source_changed;
+ bool bad_statless_params;
};
static inline struct vicodec_ctx *file2ctx(struct file *file)
@@ -169,10 +171,38 @@ static int device_process(struct vicodec_ctx *ctx,
u8 *p_src, *p_dst;
int ret;
+ if (ctx->is_stateless) {
+ unsigned int comp_frame_size;
+
+ p_src = vb2_plane_vaddr(&src_vb->vb2_buf, 0);
+
+ memcpy(&state->header, p_src, sizeof(struct fwht_cframe_hdr));
+ comp_frame_size = ntohl(ctx->state.header.size);
+ if (comp_frame_size > ctx->comp_max_size)
+ return -EINVAL;
+ memcpy(state->compressed_frame,
+ p_src + sizeof(struct fwht_cframe_hdr), comp_frame_size);
+ }
+
if (ctx->is_enc)
p_src = vb2_plane_vaddr(&src_vb->vb2_buf, 0);
else
p_src = state->compressed_frame;
+
+ if (ctx->is_stateless) {
+ struct media_request *src_req = src_vb->vb2_buf.req_obj.req;
+
+ if (!src_req) {
+ v4l2_err(&dev->v4l2_dev, "%s: request is NULL\n",
+ __func__);
+ return -EFAULT;
+ }
+ ctx->cur_req = src_req;
+ v4l2_ctrl_request_setup(src_req, &ctx->hdl);
+ ctx->cur_req = NULL;
+ if (ctx->bad_statless_params)
+ return -EINVAL;
+ }
p_dst = vb2_plane_vaddr(&dst_vb->vb2_buf, 0);
if (!p_src || !p_dst) {
v4l2_err(&dev->v4l2_dev,
@@ -200,7 +230,8 @@ static int device_process(struct vicodec_ctx *ctx,
ret = v4l2_fwht_decode(state, p_src, p_dst);
if (ret < 0)
return ret;
- copy_cap_to_ref(p_dst, ctx->state.info, &ctx->state);
+ if (!ctx->is_stateless)
+ copy_cap_to_ref(p_dst, ctx->state.info, &ctx->state);
vb2_set_plane_payload(&dst_vb->vb2_buf, 0, q_dst->sizeimage);
}
@@ -294,13 +325,21 @@ static void device_run(void *priv)
v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, !ctx->is_enc);
ctx->last_dst_buf = dst_buf;
+ if (ctx->is_stateless) {
+ struct media_request *src_req;
+
+ src_req = src_buf->vb2_buf.req_obj.req;
+ if (src_req)
+ v4l2_ctrl_request_complete(src_req, &ctx->hdl);
+ }
+
spin_lock(ctx->lock);
if (!ctx->comp_has_next_frame && src_buf == ctx->last_src_buf) {
dst_buf->flags |= V4L2_BUF_FLAG_LAST;
v4l2_event_queue_fh(&ctx->fh, &eos_event);
}
- if (ctx->is_enc) {
+ if (ctx->is_enc || ctx->is_stateless) {
src_buf->sequence = q_src->sequence++;
src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
v4l2_m2m_buf_done(src_buf, state);
@@ -452,7 +491,7 @@ static int job_ready(void *priv)
if (ctx->source_changed)
return 0;
- if (ctx->is_enc || ctx->comp_has_frame)
+ if (ctx->is_stateless || ctx->is_enc || ctx->comp_has_frame)
return 1;
restart:
@@ -1212,6 +1251,14 @@ static int vicodec_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
return 0;
}
+static int vicodec_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 int vicodec_buf_prepare(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
@@ -1275,10 +1322,11 @@ static void vicodec_buf_queue(struct vb2_buffer *vb)
}
/*
- * source change event is relevant only for the decoder
+ * source change event is relevant only for the stateful decoder
* in the compressed stream
*/
- if (ctx->is_enc || !V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+ if (ctx->is_stateless || ctx->is_enc ||
+ !V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
return;
}
@@ -1326,6 +1374,8 @@ static void vicodec_return_bufs(struct vb2_queue *q, u32 state)
vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
if (vbuf == NULL)
return;
+ v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
+ &ctx->hdl);
spin_lock(ctx->lock);
v4l2_m2m_buf_done(vbuf, state);
spin_unlock(ctx->lock);
@@ -1442,14 +1492,24 @@ static void vicodec_stop_streaming(struct vb2_queue *q)
}
}
+static void vicodec_buf_request_complete(struct vb2_buffer *vb)
+{
+ struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+ v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
+}
+
+
static const struct vb2_ops vicodec_qops = {
- .queue_setup = vicodec_queue_setup,
- .buf_prepare = vicodec_buf_prepare,
- .buf_queue = vicodec_buf_queue,
- .start_streaming = vicodec_start_streaming,
- .stop_streaming = vicodec_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
+ .queue_setup = vicodec_queue_setup,
+ .buf_out_validate = vicodec_buf_out_validate,
+ .buf_prepare = vicodec_buf_prepare,
+ .buf_queue = vicodec_buf_queue,
+ .buf_request_complete = vicodec_buf_request_complete,
+ .start_streaming = vicodec_start_streaming,
+ .stop_streaming = vicodec_stop_streaming,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
};
static int queue_init(void *priv, struct vb2_queue *src_vq,
@@ -1501,6 +1561,13 @@ static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct vicodec_ctx *ctx = container_of(ctrl->handler,
struct vicodec_ctx, hdl);
+ struct media_request *src_req;
+ struct vb2_v4l2_buffer *src_buf;
+ struct vb2_buffer *ref_vb2_buf;
+ u8 *ref_buf;
+ struct v4l2_ctrl_fwht_params *params;
+ struct vb2_queue *vq_cap;
+ struct fwht_raw_frame *ref_frame;
switch (ctrl->id) {
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
@@ -1511,6 +1578,49 @@ static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
case VICODEC_CID_P_FRAME_QP:
ctx->state.p_frame_qp = ctrl->val;
+ return 0;
+ case VICODEC_CID_STATELESS_FWHT:
+ if (!ctx->cur_req)
+ return 0;
+ params = (struct v4l2_ctrl_fwht_params *) ctrl->p_new.p;
+ vq_cap = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ ref_frame = &ctx->state.ref_frame;
+
+ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ if (!src_buf)
+ return 0;
+ src_req = src_buf->vb2_buf.req_obj.req;
+ if (src_req != ctx->cur_req)
+ return 0;
+
+ if (params->width > ctx->state.coded_width ||
+ params->height > ctx->state.coded_height) {
+ ctx->bad_statless_params = true;
+ return 0;
+ }
+ /*
+ * if backward_ref_ts is 0, it means there is no
+ * ref frame, so just return
+ */
+ if (params->backward_ref_ts == 0) {
+ ctx->state.visible_width = params->width;
+ ctx->state.visible_height = params->height;
+ return 0;
+ }
+ ref_vb2_buf = vb2_find_timestamp_buf(vq_cap,
+ params->backward_ref_ts, 0);
+
+ if (!ref_vb2_buf) {
+ ctx->bad_statless_params = true;
+ return 0;
+ }
+
+ ref_buf = vb2_plane_vaddr(ref_vb2_buf, 0);
+ ctx->state.visible_width = params->width;
+ ctx->state.visible_height = params->height;
+ copy_cap_to_ref(ref_buf, ctx->state.info, &ctx->state);
+
return 0;
}
return -EINVAL;
@@ -1543,6 +1653,7 @@ static const struct v4l2_ctrl_config vicodec_ctrl_p_frame = {
};
static const struct v4l2_ctrl_config vicodec_ctrl_stateless_state = {
+ .ops = &vicodec_ctrl_ops,
.id = VICODEC_CID_STATELESS_FWHT,
.elem_size = sizeof(struct v4l2_ctrl_fwht_params),
.name = "FWHT-Stateless State Params",
@@ -1666,6 +1777,67 @@ static int vicodec_release(struct file *file)
return 0;
}
+static int vicodec_request_validate(struct media_request *req)
+{
+ struct media_request_object *obj;
+ struct v4l2_ctrl_handler *parent_hdl, *hdl;
+ struct vicodec_ctx *ctx = NULL;
+ struct v4l2_ctrl *ctrl;
+ 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);
+ ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+ break;
+ }
+ }
+
+ if (!ctx) {
+ pr_err("No buffer was provided with the request\n");
+ return -ENOENT;
+ }
+
+ count = vb2_request_buffer_cnt(req);
+ if (!count) {
+ v4l2_info(&ctx->dev->v4l2_dev,
+ "No buffer was provided with the request\n");
+ return -ENOENT;
+ } else if (count > 1) {
+ v4l2_info(&ctx->dev->v4l2_dev,
+ "More than one buffer was provided with the request\n");
+ return -EINVAL;
+ }
+
+ parent_hdl = &ctx->hdl;
+
+ hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl);
+ if (!hdl) {
+ v4l2_info(&ctx->dev->v4l2_dev, "Missing codec control(s)\n");
+ return -ENOENT;
+ }
+ ctrl = v4l2_ctrl_request_hdl_ctrl_find(hdl,
+ vicodec_ctrl_stateless_state.id);
+ if (!ctrl) {
+ v4l2_info(&ctx->dev->v4l2_dev,
+ "Missing required codec control\n");
+ return -ENOENT;
+ }
+
+ if (ctrl->elem_size != vicodec_ctrl_stateless_state.elem_size) {
+ v4l2_info(&ctx->dev->v4l2_dev,
+ "wrong size, got %u expected %u\n",
+ ctrl->elem_size,
+ vicodec_ctrl_stateless_state.elem_size);
+ return -ENOENT;
+
+ }
+ return vb2_request_validate(req);
+}
+
static const struct v4l2_file_operations vicodec_fops = {
.owner = THIS_MODULE,
.open = vicodec_open,
@@ -1684,6 +1856,11 @@ static const struct video_device vicodec_videodev = {
.release = video_device_release_empty,
};
+static const struct media_device_ops vicodec_m2m_media_ops = {
+ .req_validate = vicodec_request_validate,
+ .req_queue = v4l2_m2m_request_queue,
+};
+
static const struct v4l2_m2m_ops m2m_ops = {
.device_run = device_run,
.job_ready = job_ready,
@@ -1750,6 +1927,7 @@ static int vicodec_probe(struct platform_device *pdev)
strscpy(dev->mdev.bus_info, "platform:vicodec",
sizeof(dev->mdev.bus_info));
media_device_init(&dev->mdev);
+ dev->mdev.ops = &vicodec_m2m_media_ops;
dev->v4l2_dev.mdev = &dev->mdev;
#endif
--
2.17.1
next prev parent reply other threads:[~2019-02-09 13:54 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-09 13:54 [PATCH 0/9] media: vicodec: add support to stateless decoder Dafna Hirschfeld
2019-02-09 13:54 ` [PATCH 1/9] media: vicodec: Move raw frame preparation code to a function Dafna Hirschfeld
2019-02-09 13:54 ` [PATCH 2/9] media: vicodec: add field 'buf' to fwht_raw_frame Dafna Hirschfeld
2019-02-09 13:54 ` [PATCH 3/9] media: vicodec: keep the ref frame according to the format in decoder Dafna Hirschfeld
2019-02-09 13:54 ` [PATCH 4/9] media: vicodec: add struct for encoder/decoder instance Dafna Hirschfeld
2019-02-11 8:31 ` Hans Verkuil
2019-02-09 13:54 ` [PATCH 5/9] media: vicodec: Introducing stateless fwht defs and structs Dafna Hirschfeld
2019-02-09 13:54 ` [PATCH 6/9] media: vicodec: Register another node for stateless decoder Dafna Hirschfeld
2019-02-11 8:31 ` Hans Verkuil
2019-02-09 13:54 ` [PATCH 7/9] media: vb2: Add func that return buffer by timestamp Dafna Hirschfeld
2019-02-11 10:11 ` Hans Verkuil
2019-02-09 13:54 ` [PATCH 8/9] media: vicodec: call v4l2_m2m_buf_copy_metadata also upon error Dafna Hirschfeld
2019-02-09 13:54 ` Dafna Hirschfeld [this message]
2019-02-11 10:09 ` [PATCH 9/9] media: vicodec: Add support for stateless decoder Hans Verkuil
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190209135427.20630-10-dafna3@gmail.com \
--to=dafna3@gmail.com \
--cc=helen.koike@collabora.com \
--cc=hverkuil@xs4all.nl \
--cc=linux-media@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).