Message ID | 20190215130900.86351-1-dafna3@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | add support to stateless decoder | expand |
Hi Dafna, Thank you for the patch! Yet something to improve: [auto build test ERROR on linuxtv-media/master] [also build test ERROR on next-20190215] [cannot apply to v5.0-rc4] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Dafna-Hirschfeld/add-support-to-stateless-decoder/20190216-051151 base: git://linuxtv.org/media_tree.git master reproduce: # apt-get install sparse make ARCH=x86_64 allmodconfig make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' All error/warnings (new ones prefixed by >>): >> drivers/media/platform/vicodec/vicodec-core.c:180:6: sparse: warning: symbol 'validate_stateless_params_flags' was not declared. Should it be static? >> drivers/media/platform/vicodec/vicodec-core.c:1614:15: sparse: error: no member 'requires_requests' in struct vb2_queue >> drivers/media/platform/vicodec/vicodec-core.c:1614:15: sparse: warning: generating address of non-lvalue (8) vim +/requires_requests +1614 drivers/media/platform/vicodec/vicodec-core.c 256bf813 Hans Verkuil 2018-07-20 1591 256bf813 Hans Verkuil 2018-07-20 1592 static int queue_init(void *priv, struct vb2_queue *src_vq, 256bf813 Hans Verkuil 2018-07-20 1593 struct vb2_queue *dst_vq) 256bf813 Hans Verkuil 2018-07-20 1594 { 256bf813 Hans Verkuil 2018-07-20 1595 struct vicodec_ctx *ctx = priv; 256bf813 Hans Verkuil 2018-07-20 1596 int ret; 256bf813 Hans Verkuil 2018-07-20 1597 256bf813 Hans Verkuil 2018-07-20 1598 src_vq->type = (multiplanar ? 256bf813 Hans Verkuil 2018-07-20 1599 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : 256bf813 Hans Verkuil 2018-07-20 1600 V4L2_BUF_TYPE_VIDEO_OUTPUT); 256bf813 Hans Verkuil 2018-07-20 1601 src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; 256bf813 Hans Verkuil 2018-07-20 1602 src_vq->drv_priv = ctx; 256bf813 Hans Verkuil 2018-07-20 1603 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 256bf813 Hans Verkuil 2018-07-20 1604 src_vq->ops = &vicodec_qops; 256bf813 Hans Verkuil 2018-07-20 1605 src_vq->mem_ops = &vb2_vmalloc_memops; 256bf813 Hans Verkuil 2018-07-20 1606 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; c6f483ff Dafna Hirschfeld 2019-02-15 1607 if (ctx->is_enc) c6f483ff Dafna Hirschfeld 2019-02-15 1608 src_vq->lock = &ctx->dev->stateful_enc.mutex; c6f483ff Dafna Hirschfeld 2019-02-15 1609 else if (ctx->is_stateless) c6f483ff Dafna Hirschfeld 2019-02-15 1610 src_vq->lock = &ctx->dev->stateless_dec.mutex; c6f483ff Dafna Hirschfeld 2019-02-15 1611 else c6f483ff Dafna Hirschfeld 2019-02-15 1612 src_vq->lock = &ctx->dev->stateful_dec.mutex; c6f483ff Dafna Hirschfeld 2019-02-15 1613 src_vq->supports_requests = ctx->is_stateless ? true : false; c6f483ff Dafna Hirschfeld 2019-02-15 @1614 src_vq->requires_requests = ctx->is_stateless ? true : false; 256bf813 Hans Verkuil 2018-07-20 1615 ret = vb2_queue_init(src_vq); 256bf813 Hans Verkuil 2018-07-20 1616 if (ret) 256bf813 Hans Verkuil 2018-07-20 1617 return ret; 256bf813 Hans Verkuil 2018-07-20 1618 256bf813 Hans Verkuil 2018-07-20 1619 dst_vq->type = (multiplanar ? 256bf813 Hans Verkuil 2018-07-20 1620 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : 256bf813 Hans Verkuil 2018-07-20 1621 V4L2_BUF_TYPE_VIDEO_CAPTURE); 256bf813 Hans Verkuil 2018-07-20 1622 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; 256bf813 Hans Verkuil 2018-07-20 1623 dst_vq->drv_priv = ctx; 256bf813 Hans Verkuil 2018-07-20 1624 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 256bf813 Hans Verkuil 2018-07-20 1625 dst_vq->ops = &vicodec_qops; 256bf813 Hans Verkuil 2018-07-20 1626 dst_vq->mem_ops = &vb2_vmalloc_memops; 256bf813 Hans Verkuil 2018-07-20 1627 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 256bf813 Hans Verkuil 2018-07-20 1628 dst_vq->lock = src_vq->lock; 256bf813 Hans Verkuil 2018-07-20 1629 256bf813 Hans Verkuil 2018-07-20 1630 return vb2_queue_init(dst_vq); 256bf813 Hans Verkuil 2018-07-20 1631 } 256bf813 Hans Verkuil 2018-07-20 1632 :::::: The code at line 1614 was first introduced by commit :::::: c6f483ff724e70555c1725705674f22c0ba0a119 media: vicodec: Register another node for stateless decoder :::::: TO: Dafna Hirschfeld <dafna3@gmail.com> :::::: CC: 0day robot <lkp@intel.com> --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
On 2/15/19 2:09 PM, Dafna Hirschfeld wrote: > Implement a stateless decoder for the new node. > > Signed-off-by: Dafna Hirschfeld <dafna3@gmail.com> > --- > .../media/platform/vicodec/codec-v4l2-fwht.h | 1 + > drivers/media/platform/vicodec/vicodec-core.c | 325 ++++++++++++++++-- > include/uapi/linux/v4l2-controls.h | 1 + > 3 files changed, 291 insertions(+), 36 deletions(-) > > diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.h b/drivers/media/platform/vicodec/codec-v4l2-fwht.h > index 75343cdf45e2..b58a81b35661 100644 > --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.h > +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.h > @@ -43,6 +43,7 @@ struct v4l2_fwht_state { > struct fwht_raw_frame ref_frame; > struct fwht_cframe_hdr header; > u8 *compressed_frame; > + __u64 ref_frame_ts; Use u64, it's an internal header so no need for __u64. > }; > > const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_pixfmt(u32 pixelformat); > diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c > index 031aaf83839c..b2607e9772c4 100644 > --- a/drivers/media/platform/vicodec/vicodec-core.c > +++ b/drivers/media/platform/vicodec/vicodec-core.c > @@ -160,6 +160,60 @@ static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx, > return NULL; > } > > +static bool validate_by_version(unsigned int flags, unsigned int version) > +{ > + if (!version || version > FWHT_VERSION) > + return false; > + > + if (version == FWHT_VERSION) { > + unsigned int components_num = 1 + > + ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >> > + FWHT_FL_COMPONENTS_NUM_OFFSET); > + unsigned int pixenc = flags & FWHT_FL_PIXENC_MSK; > + > + if (components_num == 0 || components_num > 4 || !pixenc) > + return false; > + } > + return true; > +} I would add this function in a separate patch and add it to the series somewhere before patch 6/10. > + > +bool validate_stateless_params_flags(const struct v4l2_ctrl_fwht_params *params, > + const struct v4l2_fwht_pixfmt_info *cur_info) > +{ > + unsigned int width_div = (params->flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2; > + unsigned int height_div = (params->flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2; > + unsigned int components_num = 3; > + unsigned int pixenc = 0; > + int i = 0; > + const struct v4l2_fwht_pixfmt_info *info = NULL; > + > + if (params->version == FWHT_VERSION) { > + components_num = 1 + ((params->flags & FWHT_FL_COMPONENTS_NUM_MSK) >> > + FWHT_FL_COMPONENTS_NUM_OFFSET); > + pixenc = (params->flags & FWHT_FL_PIXENC_MSK); > + } > + do { > + info = v4l2_fwht_default_fmt(width_div, height_div, > + components_num, pixenc, i++); I hadn't noticed when this function was added, but this can be implemented better. The last argument should be an unsigned int pointer containing the index in the v4l2_fwht_pixfmts array from which to start the for-loop. If a format was found, then the pointer is updated with a new index. This does mean that enum_fmt() needs to become a bit smarter, but right now this function is quite inefficient: as used here it is a quadratic algorithm instead of linear. This too can be fixed in a separate patch. > + if (info && info->id == cur_info->id) > + return true; > + } while (info); But in any case, what you are doing here is that you want to validate if the parameters are valid for cur_info. There is no need to walk over all formats, just check the validity. Perhaps we need a simple v4l2_fwht_valid_fmt function for this. > + return false; > +} > + > + > +static void update_state_from_header(struct vicodec_ctx *ctx) > +{ > + const struct fwht_cframe_hdr *p_hdr = &ctx->state.header; > + > + ctx->state.visible_width = ntohl(p_hdr->width); > + ctx->state.visible_height = ntohl(p_hdr->height); > + ctx->state.colorspace = ntohl(p_hdr->colorspace); > + ctx->state.xfer_func = ntohl(p_hdr->xfer_func); > + ctx->state.ycbcr_enc = ntohl(p_hdr->ycbcr_enc); > + ctx->state.quantization = ntohl(p_hdr->quantization); > +} > + > static int device_process(struct vicodec_ctx *ctx, > struct vb2_v4l2_buffer *src_vb, > struct vb2_v4l2_buffer *dst_vb) > @@ -167,12 +221,55 @@ static int device_process(struct vicodec_ctx *ctx, > struct vicodec_dev *dev = ctx->dev; > struct v4l2_fwht_state *state = &ctx->state; > u8 *p_src, *p_dst; > - int ret; > + int ret = 0; > > 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; > + unsigned int comp_frame_size; > + u8 *p_out = vb2_plane_vaddr(&src_vb->vb2_buf, 0); > + > + if (!src_req) { > + v4l2_err(&dev->v4l2_dev, "%s: request is NULL\n", > + __func__); > + return -EFAULT; This shouldn't be necessary anymore now that you set requires_requests. > + } > + ret = v4l2_ctrl_request_setup(src_req, &ctx->hdl); > + if (ret) > + return ret; > + update_state_from_header(ctx); > + > + comp_frame_size = ntohl(ctx->state.header.size); > + memcpy(state->compressed_frame, p_out, comp_frame_size); There should be no need to memcpy. For the stateless decoder you can just set state->compressed_frame to p_out (and there is no more need to allocate memory for state->compressed_frame). > + > + /* > + * set the reference buffer from the reference timestamp > + * only if this is a P-frame > + */ > + if (ntohl(ctx->state.header.flags) & FWHT_FL_P_FRAME) { > + struct vb2_buffer *ref_vb2_buf; > + u8 *ref_buf; > + int ref_buf_idx; > + struct vb2_queue *vq_cap = > + v4l2_m2m_get_vq(ctx->fh.m2m_ctx, > + V4L2_BUF_TYPE_VIDEO_CAPTURE); > + > + ref_buf_idx = vb2_find_timestamp(vq_cap, > + ctx->state.ref_frame_ts, 0); > + if (ref_buf_idx < 0) > + return -EINVAL; > + > + ref_vb2_buf = vq_cap->bufs[ref_buf_idx]; > + if (ref_vb2_buf->state == VB2_BUF_STATE_ERROR) > + ret = -EINVAL; > + ref_buf = vb2_plane_vaddr(ref_vb2_buf, 0); > + copy_cap_to_ref(ref_buf, ctx->state.info, &ctx->state); Why call this? You want the decoder to use ref_buf directly. > + } > + } > p_dst = vb2_plane_vaddr(&dst_vb->vb2_buf, 0); > if (!p_src || !p_dst) { > v4l2_err(&dev->v4l2_dev, > @@ -182,13 +279,14 @@ static int device_process(struct vicodec_ctx *ctx, > > if (ctx->is_enc) { > struct vicodec_q_data *q_src; > + int comp_sz_or_errcode; > > q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); > state->info = q_src->info; > - ret = v4l2_fwht_encode(state, p_src, p_dst); > - if (ret < 0) > - return ret; > - vb2_set_plane_payload(&dst_vb->vb2_buf, 0, ret); > + comp_sz_or_errcode = v4l2_fwht_encode(state, p_src, p_dst); > + if (comp_sz_or_errcode < 0) > + return comp_sz_or_errcode; > + vb2_set_plane_payload(&dst_vb->vb2_buf, 0, comp_sz_or_errcode); This is a cleanup and doesn't belong here. Either drop it or make it a separate patch. > } else { > struct vicodec_q_data *q_dst; > unsigned int comp_frame_size = ntohl(ctx->state.header.size); > @@ -200,11 +298,12 @@ 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); > } > - return 0; > + return ret; > } > > /* > @@ -279,9 +378,13 @@ static void device_run(void *priv) > struct vb2_v4l2_buffer *src_buf, *dst_buf; > struct vicodec_q_data *q_src, *q_dst; > u32 state; > + struct media_request *src_req; > + > > src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); > dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); > + src_req = src_buf->vb2_buf.req_obj.req; > + > q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); > q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > > @@ -300,7 +403,7 @@ static void device_run(void *priv) > 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); > @@ -312,6 +415,9 @@ static void device_run(void *priv) > ctx->comp_has_next_frame = false; > } > v4l2_m2m_buf_done(dst_buf, state); > + if (ctx->is_stateless && src_req) > + v4l2_ctrl_request_complete(src_req, &ctx->hdl); > + > ctx->comp_size = 0; > ctx->header_size = 0; > ctx->comp_magic_cnt = 0; > @@ -368,21 +474,11 @@ static bool is_header_valid(const struct fwht_cframe_hdr *p_hdr) > unsigned int version = ntohl(p_hdr->version); > unsigned int flags = ntohl(p_hdr->flags); > > - if (!version || version > FWHT_VERSION) > - return false; > - > if (w < MIN_WIDTH || w > MAX_WIDTH || h < MIN_HEIGHT || h > MAX_HEIGHT) > return false; > > - if (version == FWHT_VERSION) { > - unsigned int components_num = 1 + > - ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >> > - FWHT_FL_COMPONENTS_NUM_OFFSET); > - unsigned int pixenc = flags & FWHT_FL_PIXENC_MSK; > - > - if (components_num == 0 || components_num > 4 || !pixenc) > - return false; > - } > + if (!validate_by_version(flags, version)) > + return false; > > info = info_from_header(p_hdr); > if (!info) > @@ -400,6 +496,12 @@ static void update_capture_data_from_header(struct vicodec_ctx *ctx) > unsigned int hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2; > unsigned int hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2; > > + /* > + * This function should not be used by a statless codec since statless -> stateless > + * it changes values in q_data that are not request specific > + */ > + WARN_ON(ctx->is_stateless); > + > q_dst->info = info; > q_dst->visible_width = ntohl(p_hdr->width); > q_dst->visible_height = ntohl(p_hdr->height); > @@ -452,7 +554,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 +1314,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 +1385,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,12 +1437,33 @@ 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); > } > } > > +static unsigned int total_frame_size(struct vicodec_q_data *q_data) > +{ > + unsigned int size; > + unsigned int chroma_div; > + > + if (!q_data->info) { > + WARN_ON(1); > + return 0; > + } > + size = q_data->coded_width * q_data->coded_height; > + chroma_div = q_data->info->width_div * q_data->info->height_div; > + > + if (q_data->info->components_num == 4) > + return 2 * size + 2 * (size / chroma_div); > + else if (q_data->info->components_num == 3) > + return size + 2 * (size / chroma_div); > + return size; > +} > + > static int vicodec_start_streaming(struct vb2_queue *q, > unsigned int count) > { > @@ -1362,12 +1494,7 @@ static int vicodec_start_streaming(struct vb2_queue *q, > vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED); > return -EINVAL; > } > - if (info->components_num == 4) > - total_planes_size = 2 * size + 2 * (size / chroma_div); > - else if (info->components_num == 3) > - total_planes_size = size + 2 * (size / chroma_div); > - else > - total_planes_size = size; > + total_planes_size = total_frame_size(q_data); > > state->visible_width = q_data->visible_width; > state->visible_height = q_data->visible_height; > @@ -1442,14 +1569,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, > @@ -1498,10 +1635,60 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, > #define VICODEC_CID_P_FRAME_QP (VICODEC_CID_CUSTOM_BASE + 1) > #define VICODEC_CID_STATELESS_FWHT (VICODEC_CID_CUSTOM_BASE + 2) > > +static int vicodec_try_ctrl(struct v4l2_ctrl *ctrl) > +{ > + struct vicodec_ctx *ctx = container_of(ctrl->handler, > + struct vicodec_ctx, hdl); > + struct v4l2_ctrl_fwht_params *params; > + struct vicodec_q_data *q_dst = get_q_data(ctx, > + V4L2_BUF_TYPE_VIDEO_CAPTURE); > + > + switch (ctrl->id) { > + case VICODEC_CID_STATELESS_FWHT: > + if (!q_dst->info) > + return -EINVAL; > + params = (struct v4l2_ctrl_fwht_params *) ctrl->p_new.p; Use ctrl->p_new.p_fwht_params. > + if (params->width > q_dst->coded_width || > + params->width < MIN_WIDTH || > + params->height > q_dst->coded_height || > + params->height < MIN_HEIGHT) > + return -EINVAL; > + if (!validate_by_version(params->flags, params->version)) > + return -EINVAL; > + if (!validate_stateless_params_flags(params, q_dst->info)) > + return -EINVAL; > + if (params->comp_frame_size > total_frame_size(q_dst)) > + return -EINVAL; > + default: > + return 0; > + } > + return 0; > +} > + > +static void update_header_from_stateless_params(struct vicodec_ctx *ctx, > + struct v4l2_ctrl_fwht_params *params) > +{ > + struct fwht_cframe_hdr *p_hdr = &ctx->state.header; > + > + p_hdr->magic1 = FWHT_MAGIC1; > + p_hdr->magic2 = FWHT_MAGIC2; > + p_hdr->version = htonl(params->version); > + p_hdr->width = htonl(params->width); > + p_hdr->height = htonl(params->height); > + p_hdr->flags = htonl(params->flags); > + p_hdr->colorspace = htonl(params->colorspace); > + p_hdr->xfer_func = htonl(params->xfer_func); > + p_hdr->ycbcr_enc = htonl(params->ycbcr_enc); > + p_hdr->quantization = htonl(params->quantization); > + p_hdr->size = htonl(params->comp_frame_size); > +} > + > + > static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl) > { > struct vicodec_ctx *ctx = container_of(ctrl->handler, > struct vicodec_ctx, hdl); > + struct v4l2_ctrl_fwht_params *params; > > switch (ctrl->id) { > case V4L2_CID_MPEG_VIDEO_GOP_SIZE: > @@ -1513,12 +1700,18 @@ static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl) > case VICODEC_CID_P_FRAME_QP: > ctx->state.p_frame_qp = ctrl->val; > return 0; > + case VICODEC_CID_STATELESS_FWHT: > + params = (struct v4l2_ctrl_fwht_params *) ctrl->p_new.p; Ditto. > + update_header_from_stateless_params(ctx, params); > + ctx->state.ref_frame_ts = params->backward_ref_ts; > + return 0; > } > return -EINVAL; > } > > static const struct v4l2_ctrl_ops vicodec_ctrl_ops = { > .s_ctrl = vicodec_s_ctrl, > + .try_ctrl = vicodec_try_ctrl, > }; > > static const struct v4l2_ctrl_config vicodec_ctrl_i_frame = { > @@ -1544,6 +1737,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", > @@ -1667,6 +1861,59 @@ 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"); Make this v4l2_info. > + 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\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; > + } > + > + return vb2_request_validate(req); > +} > + > static const struct v4l2_file_operations vicodec_fops = { > .owner = THIS_MODULE, > .open = vicodec_open, > @@ -1685,6 +1932,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, > @@ -1751,6 +2003,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 > > diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h > index 0358a3b22391..ce6ee8af466e 100644 > --- a/include/uapi/linux/v4l2-controls.h > +++ b/include/uapi/linux/v4l2-controls.h > @@ -1099,6 +1099,7 @@ enum v4l2_detect_md_mode { > > struct v4l2_ctrl_fwht_params { > __u64 backward_ref_ts; > + __u32 version; > __u32 width; > __u32 height; > __u32 flags; > This should be moved to patch 6/10. When you start work on v3 please rebase to the latest master first. Regards, Hans
diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.h b/drivers/media/platform/vicodec/codec-v4l2-fwht.h index 75343cdf45e2..b58a81b35661 100644 --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.h +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.h @@ -43,6 +43,7 @@ struct v4l2_fwht_state { struct fwht_raw_frame ref_frame; struct fwht_cframe_hdr header; u8 *compressed_frame; + __u64 ref_frame_ts; }; const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_pixfmt(u32 pixelformat); diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 031aaf83839c..b2607e9772c4 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -160,6 +160,60 @@ static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx, return NULL; } +static bool validate_by_version(unsigned int flags, unsigned int version) +{ + if (!version || version > FWHT_VERSION) + return false; + + if (version == FWHT_VERSION) { + unsigned int components_num = 1 + + ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >> + FWHT_FL_COMPONENTS_NUM_OFFSET); + unsigned int pixenc = flags & FWHT_FL_PIXENC_MSK; + + if (components_num == 0 || components_num > 4 || !pixenc) + return false; + } + return true; +} + +bool validate_stateless_params_flags(const struct v4l2_ctrl_fwht_params *params, + const struct v4l2_fwht_pixfmt_info *cur_info) +{ + unsigned int width_div = (params->flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2; + unsigned int height_div = (params->flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2; + unsigned int components_num = 3; + unsigned int pixenc = 0; + int i = 0; + const struct v4l2_fwht_pixfmt_info *info = NULL; + + if (params->version == FWHT_VERSION) { + components_num = 1 + ((params->flags & FWHT_FL_COMPONENTS_NUM_MSK) >> + FWHT_FL_COMPONENTS_NUM_OFFSET); + pixenc = (params->flags & FWHT_FL_PIXENC_MSK); + } + do { + info = v4l2_fwht_default_fmt(width_div, height_div, + components_num, pixenc, i++); + if (info && info->id == cur_info->id) + return true; + } while (info); + return false; +} + + +static void update_state_from_header(struct vicodec_ctx *ctx) +{ + const struct fwht_cframe_hdr *p_hdr = &ctx->state.header; + + ctx->state.visible_width = ntohl(p_hdr->width); + ctx->state.visible_height = ntohl(p_hdr->height); + ctx->state.colorspace = ntohl(p_hdr->colorspace); + ctx->state.xfer_func = ntohl(p_hdr->xfer_func); + ctx->state.ycbcr_enc = ntohl(p_hdr->ycbcr_enc); + ctx->state.quantization = ntohl(p_hdr->quantization); +} + static int device_process(struct vicodec_ctx *ctx, struct vb2_v4l2_buffer *src_vb, struct vb2_v4l2_buffer *dst_vb) @@ -167,12 +221,55 @@ static int device_process(struct vicodec_ctx *ctx, struct vicodec_dev *dev = ctx->dev; struct v4l2_fwht_state *state = &ctx->state; u8 *p_src, *p_dst; - int ret; + int ret = 0; 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; + unsigned int comp_frame_size; + u8 *p_out = vb2_plane_vaddr(&src_vb->vb2_buf, 0); + + if (!src_req) { + v4l2_err(&dev->v4l2_dev, "%s: request is NULL\n", + __func__); + return -EFAULT; + } + ret = v4l2_ctrl_request_setup(src_req, &ctx->hdl); + if (ret) + return ret; + update_state_from_header(ctx); + + comp_frame_size = ntohl(ctx->state.header.size); + memcpy(state->compressed_frame, p_out, comp_frame_size); + + /* + * set the reference buffer from the reference timestamp + * only if this is a P-frame + */ + if (ntohl(ctx->state.header.flags) & FWHT_FL_P_FRAME) { + struct vb2_buffer *ref_vb2_buf; + u8 *ref_buf; + int ref_buf_idx; + struct vb2_queue *vq_cap = + v4l2_m2m_get_vq(ctx->fh.m2m_ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE); + + ref_buf_idx = vb2_find_timestamp(vq_cap, + ctx->state.ref_frame_ts, 0); + if (ref_buf_idx < 0) + return -EINVAL; + + ref_vb2_buf = vq_cap->bufs[ref_buf_idx]; + if (ref_vb2_buf->state == VB2_BUF_STATE_ERROR) + ret = -EINVAL; + ref_buf = vb2_plane_vaddr(ref_vb2_buf, 0); + copy_cap_to_ref(ref_buf, ctx->state.info, &ctx->state); + } + } p_dst = vb2_plane_vaddr(&dst_vb->vb2_buf, 0); if (!p_src || !p_dst) { v4l2_err(&dev->v4l2_dev, @@ -182,13 +279,14 @@ static int device_process(struct vicodec_ctx *ctx, if (ctx->is_enc) { struct vicodec_q_data *q_src; + int comp_sz_or_errcode; q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); state->info = q_src->info; - ret = v4l2_fwht_encode(state, p_src, p_dst); - if (ret < 0) - return ret; - vb2_set_plane_payload(&dst_vb->vb2_buf, 0, ret); + comp_sz_or_errcode = v4l2_fwht_encode(state, p_src, p_dst); + if (comp_sz_or_errcode < 0) + return comp_sz_or_errcode; + vb2_set_plane_payload(&dst_vb->vb2_buf, 0, comp_sz_or_errcode); } else { struct vicodec_q_data *q_dst; unsigned int comp_frame_size = ntohl(ctx->state.header.size); @@ -200,11 +298,12 @@ 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); } - return 0; + return ret; } /* @@ -279,9 +378,13 @@ static void device_run(void *priv) struct vb2_v4l2_buffer *src_buf, *dst_buf; struct vicodec_q_data *q_src, *q_dst; u32 state; + struct media_request *src_req; + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + src_req = src_buf->vb2_buf.req_obj.req; + q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); @@ -300,7 +403,7 @@ static void device_run(void *priv) 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); @@ -312,6 +415,9 @@ static void device_run(void *priv) ctx->comp_has_next_frame = false; } v4l2_m2m_buf_done(dst_buf, state); + if (ctx->is_stateless && src_req) + v4l2_ctrl_request_complete(src_req, &ctx->hdl); + ctx->comp_size = 0; ctx->header_size = 0; ctx->comp_magic_cnt = 0; @@ -368,21 +474,11 @@ static bool is_header_valid(const struct fwht_cframe_hdr *p_hdr) unsigned int version = ntohl(p_hdr->version); unsigned int flags = ntohl(p_hdr->flags); - if (!version || version > FWHT_VERSION) - return false; - if (w < MIN_WIDTH || w > MAX_WIDTH || h < MIN_HEIGHT || h > MAX_HEIGHT) return false; - if (version == FWHT_VERSION) { - unsigned int components_num = 1 + - ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >> - FWHT_FL_COMPONENTS_NUM_OFFSET); - unsigned int pixenc = flags & FWHT_FL_PIXENC_MSK; - - if (components_num == 0 || components_num > 4 || !pixenc) - return false; - } + if (!validate_by_version(flags, version)) + return false; info = info_from_header(p_hdr); if (!info) @@ -400,6 +496,12 @@ static void update_capture_data_from_header(struct vicodec_ctx *ctx) unsigned int hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2; unsigned int hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2; + /* + * This function should not be used by a statless codec since + * it changes values in q_data that are not request specific + */ + WARN_ON(ctx->is_stateless); + q_dst->info = info; q_dst->visible_width = ntohl(p_hdr->width); q_dst->visible_height = ntohl(p_hdr->height); @@ -452,7 +554,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 +1314,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 +1385,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,12 +1437,33 @@ 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); } } +static unsigned int total_frame_size(struct vicodec_q_data *q_data) +{ + unsigned int size; + unsigned int chroma_div; + + if (!q_data->info) { + WARN_ON(1); + return 0; + } + size = q_data->coded_width * q_data->coded_height; + chroma_div = q_data->info->width_div * q_data->info->height_div; + + if (q_data->info->components_num == 4) + return 2 * size + 2 * (size / chroma_div); + else if (q_data->info->components_num == 3) + return size + 2 * (size / chroma_div); + return size; +} + static int vicodec_start_streaming(struct vb2_queue *q, unsigned int count) { @@ -1362,12 +1494,7 @@ static int vicodec_start_streaming(struct vb2_queue *q, vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED); return -EINVAL; } - if (info->components_num == 4) - total_planes_size = 2 * size + 2 * (size / chroma_div); - else if (info->components_num == 3) - total_planes_size = size + 2 * (size / chroma_div); - else - total_planes_size = size; + total_planes_size = total_frame_size(q_data); state->visible_width = q_data->visible_width; state->visible_height = q_data->visible_height; @@ -1442,14 +1569,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, @@ -1498,10 +1635,60 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, #define VICODEC_CID_P_FRAME_QP (VICODEC_CID_CUSTOM_BASE + 1) #define VICODEC_CID_STATELESS_FWHT (VICODEC_CID_CUSTOM_BASE + 2) +static int vicodec_try_ctrl(struct v4l2_ctrl *ctrl) +{ + struct vicodec_ctx *ctx = container_of(ctrl->handler, + struct vicodec_ctx, hdl); + struct v4l2_ctrl_fwht_params *params; + struct vicodec_q_data *q_dst = get_q_data(ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE); + + switch (ctrl->id) { + case VICODEC_CID_STATELESS_FWHT: + if (!q_dst->info) + return -EINVAL; + params = (struct v4l2_ctrl_fwht_params *) ctrl->p_new.p; + if (params->width > q_dst->coded_width || + params->width < MIN_WIDTH || + params->height > q_dst->coded_height || + params->height < MIN_HEIGHT) + return -EINVAL; + if (!validate_by_version(params->flags, params->version)) + return -EINVAL; + if (!validate_stateless_params_flags(params, q_dst->info)) + return -EINVAL; + if (params->comp_frame_size > total_frame_size(q_dst)) + return -EINVAL; + default: + return 0; + } + return 0; +} + +static void update_header_from_stateless_params(struct vicodec_ctx *ctx, + struct v4l2_ctrl_fwht_params *params) +{ + struct fwht_cframe_hdr *p_hdr = &ctx->state.header; + + p_hdr->magic1 = FWHT_MAGIC1; + p_hdr->magic2 = FWHT_MAGIC2; + p_hdr->version = htonl(params->version); + p_hdr->width = htonl(params->width); + p_hdr->height = htonl(params->height); + p_hdr->flags = htonl(params->flags); + p_hdr->colorspace = htonl(params->colorspace); + p_hdr->xfer_func = htonl(params->xfer_func); + p_hdr->ycbcr_enc = htonl(params->ycbcr_enc); + p_hdr->quantization = htonl(params->quantization); + p_hdr->size = htonl(params->comp_frame_size); +} + + static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl) { struct vicodec_ctx *ctx = container_of(ctrl->handler, struct vicodec_ctx, hdl); + struct v4l2_ctrl_fwht_params *params; switch (ctrl->id) { case V4L2_CID_MPEG_VIDEO_GOP_SIZE: @@ -1513,12 +1700,18 @@ static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl) case VICODEC_CID_P_FRAME_QP: ctx->state.p_frame_qp = ctrl->val; return 0; + case VICODEC_CID_STATELESS_FWHT: + params = (struct v4l2_ctrl_fwht_params *) ctrl->p_new.p; + update_header_from_stateless_params(ctx, params); + ctx->state.ref_frame_ts = params->backward_ref_ts; + return 0; } return -EINVAL; } static const struct v4l2_ctrl_ops vicodec_ctrl_ops = { .s_ctrl = vicodec_s_ctrl, + .try_ctrl = vicodec_try_ctrl, }; static const struct v4l2_ctrl_config vicodec_ctrl_i_frame = { @@ -1544,6 +1737,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", @@ -1667,6 +1861,59 @@ 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\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; + } + + return vb2_request_validate(req); +} + static const struct v4l2_file_operations vicodec_fops = { .owner = THIS_MODULE, .open = vicodec_open, @@ -1685,6 +1932,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, @@ -1751,6 +2003,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 diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 0358a3b22391..ce6ee8af466e 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -1099,6 +1099,7 @@ enum v4l2_detect_md_mode { struct v4l2_ctrl_fwht_params { __u64 backward_ref_ts; + __u32 version; __u32 width; __u32 height; __u32 flags;
Implement a stateless decoder for the new node. Signed-off-by: Dafna Hirschfeld <dafna3@gmail.com> --- .../media/platform/vicodec/codec-v4l2-fwht.h | 1 + drivers/media/platform/vicodec/vicodec-core.c | 325 ++++++++++++++++-- include/uapi/linux/v4l2-controls.h | 1 + 3 files changed, 291 insertions(+), 36 deletions(-)