mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-18 19:05:39 +00:00
media: hantro: Implement support for encoder commands
The V4L2 stateful encoder uAPI specification requires that drivers support the ENCODER_CMD ioctl to allow draining of buffers. This however was not implemented, and causes issues for some userspace applications. Implement support for the ENCODER_CMD ioctl using v4l2-mem2mem helpers. This is entirely based on existing code found in the vicodec test driver. Fixes: 775fec69008d ("media: add Rockchip VPU JPEG encoder driver") Signed-off-by: Chen-Yu Tsai <wenst@chromium.org> Reviewed-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
parent
acd134bca2
commit
daf3999c12
@ -56,6 +56,10 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts)
|
||||
return hantro_get_dec_buf_addr(ctx, buf);
|
||||
}
|
||||
|
||||
static const struct v4l2_event hantro_eos_event = {
|
||||
.type = V4L2_EVENT_EOS
|
||||
};
|
||||
|
||||
static void hantro_job_finish_no_pm(struct hantro_dev *vpu,
|
||||
struct hantro_ctx *ctx,
|
||||
enum vb2_buffer_state result)
|
||||
@ -73,6 +77,12 @@ static void hantro_job_finish_no_pm(struct hantro_dev *vpu,
|
||||
src->sequence = ctx->sequence_out++;
|
||||
dst->sequence = ctx->sequence_cap++;
|
||||
|
||||
if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src)) {
|
||||
dst->flags |= V4L2_BUF_FLAG_LAST;
|
||||
v4l2_event_queue_fh(&ctx->fh, &hantro_eos_event);
|
||||
v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
|
||||
}
|
||||
|
||||
v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx,
|
||||
result);
|
||||
}
|
||||
@ -810,10 +820,13 @@ static int hantro_add_func(struct hantro_dev *vpu, unsigned int funcid)
|
||||
snprintf(vfd->name, sizeof(vfd->name), "%s-%s", match->compatible,
|
||||
funcid == MEDIA_ENT_F_PROC_VIDEO_ENCODER ? "enc" : "dec");
|
||||
|
||||
if (funcid == MEDIA_ENT_F_PROC_VIDEO_ENCODER)
|
||||
if (funcid == MEDIA_ENT_F_PROC_VIDEO_ENCODER) {
|
||||
vpu->encoder = func;
|
||||
else
|
||||
} else {
|
||||
vpu->decoder = func;
|
||||
v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
|
||||
v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
|
||||
}
|
||||
|
||||
video_set_drvdata(vfd, vpu);
|
||||
|
||||
|
@ -628,6 +628,38 @@ static int vidioc_s_selection(struct file *file, void *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct v4l2_event hantro_eos_event = {
|
||||
.type = V4L2_EVENT_EOS
|
||||
};
|
||||
|
||||
static int vidioc_encoder_cmd(struct file *file, void *priv,
|
||||
struct v4l2_encoder_cmd *ec)
|
||||
{
|
||||
struct hantro_ctx *ctx = fh_to_ctx(priv);
|
||||
int ret;
|
||||
|
||||
ret = v4l2_m2m_ioctl_try_encoder_cmd(file, priv, ec);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!vb2_is_streaming(v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx)) ||
|
||||
!vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx)))
|
||||
return 0;
|
||||
|
||||
ret = v4l2_m2m_ioctl_encoder_cmd(file, priv, ec);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ec->cmd == V4L2_ENC_CMD_STOP &&
|
||||
v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
|
||||
v4l2_event_queue_fh(&ctx->fh, &hantro_eos_event);
|
||||
|
||||
if (ec->cmd == V4L2_ENC_CMD_START)
|
||||
vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct v4l2_ioctl_ops hantro_ioctl_ops = {
|
||||
.vidioc_querycap = vidioc_querycap,
|
||||
.vidioc_enum_framesizes = vidioc_enum_framesizes,
|
||||
@ -657,6 +689,9 @@ const struct v4l2_ioctl_ops hantro_ioctl_ops = {
|
||||
|
||||
.vidioc_g_selection = vidioc_g_selection,
|
||||
.vidioc_s_selection = vidioc_s_selection,
|
||||
|
||||
.vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
|
||||
.vidioc_encoder_cmd = vidioc_encoder_cmd,
|
||||
};
|
||||
|
||||
static int
|
||||
@ -744,6 +779,22 @@ static void hantro_buf_queue(struct vb2_buffer *vb)
|
||||
struct hantro_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
|
||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||
|
||||
if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&
|
||||
vb2_is_streaming(vb->vb2_queue) &&
|
||||
v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < vb->num_planes; i++)
|
||||
vb2_set_plane_payload(vb, i, 0);
|
||||
|
||||
vbuf->field = V4L2_FIELD_NONE;
|
||||
vbuf->sequence = ctx->sequence_cap++;
|
||||
|
||||
v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf);
|
||||
v4l2_event_queue_fh(&ctx->fh, &hantro_eos_event);
|
||||
return;
|
||||
}
|
||||
|
||||
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
|
||||
}
|
||||
|
||||
@ -759,6 +810,8 @@ static int hantro_start_streaming(struct vb2_queue *q, unsigned int count)
|
||||
struct hantro_ctx *ctx = vb2_get_drv_priv(q);
|
||||
int ret = 0;
|
||||
|
||||
v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);
|
||||
|
||||
if (V4L2_TYPE_IS_OUTPUT(q->type))
|
||||
ctx->sequence_out = 0;
|
||||
else
|
||||
@ -831,6 +884,12 @@ static void hantro_stop_streaming(struct vb2_queue *q)
|
||||
hantro_return_bufs(q, v4l2_m2m_src_buf_remove);
|
||||
else
|
||||
hantro_return_bufs(q, v4l2_m2m_dst_buf_remove);
|
||||
|
||||
v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);
|
||||
|
||||
if (V4L2_TYPE_IS_OUTPUT(q->type) &&
|
||||
v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
|
||||
v4l2_event_queue_fh(&ctx->fh, &hantro_eos_event);
|
||||
}
|
||||
|
||||
static void hantro_buf_request_complete(struct vb2_buffer *vb)
|
||||
|
Loading…
x
Reference in New Issue
Block a user