1 // SPDX-License-Identifier: GPL-2.0+
2 /* Encoder for virtio video device.
4 * Copyright 2020 OpenSynergy GmbH.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <linux/version.h>
21 #include <media/v4l2-event.h>
22 #include <media/v4l2-ioctl.h>
24 #include "virtio_video.h"
26 static int virtio_video_enc_start_streaming(struct vb2_queue *vq,
29 struct virtio_video_stream *stream = vb2_get_drv_priv(vq);
30 bool input_queue = V4L2_TYPE_IS_OUTPUT(vq->type);
32 if (virtio_video_state(stream) == STREAM_STATE_ERROR)
35 if (virtio_video_state(stream) == STREAM_STATE_INIT ||
37 virtio_video_state(stream) == STREAM_STATE_RESET) ||
39 virtio_video_state(stream) == STREAM_STATE_STOPPED))
40 virtio_video_state_update(stream, STREAM_STATE_RUNNING);
45 static void virtio_video_enc_stop_streaming(struct vb2_queue *vq)
48 struct virtio_video_stream *stream = vb2_get_drv_priv(vq);
50 if (V4L2_TYPE_IS_OUTPUT(vq->type))
51 queue_type = VIRTIO_VIDEO_QUEUE_TYPE_INPUT;
53 queue_type = VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT;
55 ret = virtio_video_queue_release_buffers(stream, queue_type);
59 vb2_wait_for_all_buffers(vq);
61 if (V4L2_TYPE_IS_OUTPUT(vq->type))
62 virtio_video_state_update(stream, STREAM_STATE_STOPPED);
64 virtio_video_state_update(stream, STREAM_STATE_RESET);
67 static const struct vb2_ops virtio_video_enc_qops = {
68 .queue_setup = virtio_video_queue_setup,
69 .buf_init = virtio_video_buf_init,
70 .buf_cleanup = virtio_video_buf_cleanup,
71 .buf_queue = virtio_video_buf_queue,
72 .start_streaming = virtio_video_enc_start_streaming,
73 .stop_streaming = virtio_video_enc_stop_streaming,
74 .wait_prepare = vb2_ops_wait_prepare,
75 .wait_finish = vb2_ops_wait_finish,
78 static int virtio_video_enc_s_ctrl(struct v4l2_ctrl *ctrl)
81 struct virtio_video_stream *stream = ctrl2stream(ctrl);
82 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
83 uint32_t control, value;
85 if (virtio_video_state(stream) == STREAM_STATE_ERROR)
88 control = virtio_video_v4l2_control_to_virtio(ctrl->id);
91 case V4L2_CID_MPEG_VIDEO_BITRATE:
92 ret = virtio_video_cmd_set_control(vvd, stream->stream_id,
95 case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
96 value = virtio_video_v4l2_level_to_virtio(ctrl->val);
97 ret = virtio_video_cmd_set_control(vvd, stream->stream_id,
100 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
101 value = virtio_video_v4l2_profile_to_virtio(ctrl->val);
102 ret = virtio_video_cmd_set_control(vvd, stream->stream_id,
113 static int virtio_video_enc_g_ctrl(struct v4l2_ctrl *ctrl)
116 struct virtio_video_stream *stream = ctrl2stream(ctrl);
118 if (virtio_video_state(stream) == STREAM_STATE_ERROR)
122 case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
123 if (virtio_video_state(stream) >= STREAM_STATE_INIT)
124 ctrl->val = stream->in_info.min_buffers;
136 static const struct v4l2_ctrl_ops virtio_video_enc_ctrl_ops = {
137 .g_volatile_ctrl = virtio_video_enc_g_ctrl,
138 .s_ctrl = virtio_video_enc_s_ctrl,
141 int virtio_video_enc_init_ctrls(struct virtio_video_stream *stream)
143 struct v4l2_ctrl *ctrl;
144 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
145 struct video_control_format *c_fmt = NULL;
147 v4l2_ctrl_handler_init(&stream->ctrl_handler, 1);
149 ctrl = v4l2_ctrl_new_std(&stream->ctrl_handler,
150 &virtio_video_enc_ctrl_ops,
151 V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
152 MIN_BUFS_MIN, MIN_BUFS_MAX, MIN_BUFS_STEP,
156 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
158 list_for_each_entry(c_fmt, &vvd->controls_fmt_list,
159 controls_list_entry) {
160 switch (c_fmt->format) {
161 case V4L2_PIX_FMT_H264:
163 v4l2_ctrl_new_std_menu
164 (&stream->ctrl_handler,
165 &virtio_video_enc_ctrl_ops,
166 V4L2_CID_MPEG_VIDEO_H264_PROFILE,
168 c_fmt->profile->skip_mask,
169 c_fmt->profile->min);
172 v4l2_ctrl_new_std_menu
173 (&stream->ctrl_handler,
174 &virtio_video_enc_ctrl_ops,
175 V4L2_CID_MPEG_VIDEO_H264_LEVEL,
177 c_fmt->level->skip_mask,
181 v4l2_dbg(1, vvd->debug,
182 &vvd->v4l2_dev, "unsupported format\n");
187 if (stream->control.bitrate) {
188 v4l2_ctrl_new_std(&stream->ctrl_handler,
189 &virtio_video_enc_ctrl_ops,
190 V4L2_CID_MPEG_VIDEO_BITRATE,
192 1, stream->control.bitrate);
195 if (stream->ctrl_handler.error)
196 return stream->ctrl_handler.error;
198 v4l2_ctrl_handler_setup(&stream->ctrl_handler);
203 int virtio_video_enc_init_queues(void *priv, struct vb2_queue *src_vq,
204 struct vb2_queue *dst_vq)
207 struct virtio_video_stream *stream = priv;
208 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
209 struct device *dev = vvd->v4l2_dev.dev;
211 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
212 src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
213 src_vq->drv_priv = stream;
214 src_vq->buf_struct_size = sizeof(struct virtio_video_buffer);
215 src_vq->ops = &virtio_video_enc_qops;
216 src_vq->mem_ops = virtio_video_mem_ops(vvd);
217 src_vq->min_buffers_needed = stream->in_info.min_buffers;
218 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
219 src_vq->lock = &stream->vq_mutex;
220 src_vq->gfp_flags = virtio_video_gfp_flags(vvd);
223 ret = vb2_queue_init(src_vq);
227 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
228 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
229 dst_vq->drv_priv = stream;
230 dst_vq->buf_struct_size = sizeof(struct virtio_video_buffer);
231 dst_vq->ops = &virtio_video_enc_qops;
232 dst_vq->mem_ops = virtio_video_mem_ops(vvd);
233 dst_vq->min_buffers_needed = stream->out_info.min_buffers;
234 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
235 dst_vq->lock = &stream->vq_mutex;
236 dst_vq->gfp_flags = virtio_video_gfp_flags(vvd);
239 return vb2_queue_init(dst_vq);
242 static int virtio_video_try_encoder_cmd(struct file *file, void *fh,
243 struct v4l2_encoder_cmd *cmd)
245 struct virtio_video_stream *stream = file2stream(file);
246 struct virtio_video_device *vvd = video_drvdata(file);
248 if (virtio_video_state(stream) == STREAM_STATE_ERROR)
251 if (virtio_video_state(stream) == STREAM_STATE_DRAIN)
255 case V4L2_ENC_CMD_STOP:
256 case V4L2_ENC_CMD_START:
257 if (cmd->flags != 0) {
258 v4l2_err(&vvd->v4l2_dev, "flags=%u are not supported",
270 static int virtio_video_encoder_cmd(struct file *file, void *fh,
271 struct v4l2_encoder_cmd *cmd)
274 struct vb2_queue *src_vq, *dst_vq;
275 struct virtio_video_stream *stream = file2stream(file);
276 struct virtio_video_device *vvd = video_drvdata(file);
278 ret = virtio_video_try_encoder_cmd(file, fh, cmd);
282 dst_vq = v4l2_m2m_get_vq(stream->fh.m2m_ctx,
283 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
286 case V4L2_ENC_CMD_START:
287 vb2_clear_last_buffer_dequeued(dst_vq);
288 virtio_video_state_update(stream, STREAM_STATE_RUNNING);
290 case V4L2_ENC_CMD_STOP:
291 src_vq = v4l2_m2m_get_vq(stream->fh.m2m_ctx,
292 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
294 if (!vb2_is_streaming(src_vq)) {
295 v4l2_dbg(1, vvd->debug,
296 &vvd->v4l2_dev, "output is not streaming\n");
300 if (!vb2_is_streaming(dst_vq)) {
301 v4l2_dbg(1, vvd->debug,
302 &vvd->v4l2_dev, "capture is not streaming\n");
306 ret = virtio_video_cmd_stream_drain(vvd, stream->stream_id);
308 v4l2_err(&vvd->v4l2_dev, "failed to drain stream\n");
312 virtio_video_state_update(stream, STREAM_STATE_DRAIN);
321 static int virtio_video_enc_enum_fmt_vid_cap(struct file *file, void *fh,
322 struct v4l2_fmtdesc *f)
324 struct virtio_video_stream *stream = file2stream(file);
325 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
326 struct video_format *fmt;
329 if (virtio_video_state(stream) == STREAM_STATE_ERROR)
332 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
335 if (f->index >= vvd->num_output_fmts)
338 list_for_each_entry(fmt, &vvd->output_fmt_list, formats_list_entry) {
339 if (f->index == idx) {
340 f->pixelformat = fmt->desc.format;
348 static int virtio_video_enc_enum_fmt_vid_out(struct file *file, void *fh,
349 struct v4l2_fmtdesc *f)
351 struct virtio_video_stream *stream = file2stream(file);
352 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
353 struct video_format_info *info = NULL;
354 struct video_format *fmt = NULL;
355 unsigned long output_mask = 0;
356 int idx = 0, bit_num = 0;
358 if (virtio_video_state(stream) == STREAM_STATE_ERROR)
361 if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
364 if (f->index >= vvd->num_input_fmts)
367 info = &stream->out_info;
368 list_for_each_entry(fmt, &vvd->output_fmt_list, formats_list_entry) {
369 if (info->fourcc_format == fmt->desc.format) {
370 output_mask = fmt->desc.mask;
375 if (output_mask == 0)
378 list_for_each_entry(fmt, &vvd->input_fmt_list, formats_list_entry) {
379 if (test_bit(bit_num, &output_mask)) {
380 if (f->index == idx) {
381 f->pixelformat = fmt->desc.format;
391 static int virtio_video_enc_s_fmt(struct file *file, void *fh,
392 struct v4l2_format *f)
395 struct virtio_video_stream *stream = file2stream(file);
397 ret = virtio_video_s_fmt(file, fh, f);
401 if (!V4L2_TYPE_IS_OUTPUT(f->type)) {
402 if (virtio_video_state(stream) == STREAM_STATE_IDLE)
403 virtio_video_state_update(stream, STREAM_STATE_INIT);
409 static int virtio_video_enc_try_framerate(struct virtio_video_stream *stream,
413 struct video_format_frame *frame = NULL;
415 if (stream->current_frame == NULL)
418 frame = stream->current_frame;
419 for (rate_idx = 0; rate_idx < frame->frame.num_rates; rate_idx++) {
420 struct virtio_video_format_range *frame_rate =
421 &frame->frame_rates[rate_idx];
423 if (within_range(frame_rate->min, fps, frame_rate->max))
430 static void virtio_video_timeperframe_from_info(struct video_format_info *info,
431 struct v4l2_fract *timeperframe)
433 timeperframe->numerator = 1;
434 timeperframe->denominator = info->frame_rate;
437 static int virtio_video_enc_g_parm(struct file *file, void *priv,
438 struct v4l2_streamparm *a)
440 struct virtio_video_stream *stream = file2stream(file);
441 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
442 struct v4l2_outputparm *out = &a->parm.output;
443 struct v4l2_fract *timeperframe = &out->timeperframe;
445 if (virtio_video_state(stream) == STREAM_STATE_ERROR)
448 if (!V4L2_TYPE_IS_OUTPUT(a->type)) {
449 v4l2_err(&vvd->v4l2_dev,
450 "getting FPS is only possible for the output queue\n");
454 out->capability = V4L2_CAP_TIMEPERFRAME;
455 virtio_video_timeperframe_from_info(&stream->in_info, timeperframe);
460 static int virtio_video_enc_s_parm(struct file *file, void *priv,
461 struct v4l2_streamparm *a)
464 u64 frame_interval, frame_rate;
465 struct video_format_info info;
466 struct virtio_video_stream *stream = file2stream(file);
467 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
468 struct v4l2_outputparm *out = &a->parm.output;
469 struct v4l2_fract *timeperframe = &out->timeperframe;
471 if (virtio_video_state(stream) == STREAM_STATE_ERROR)
474 if (V4L2_TYPE_IS_OUTPUT(a->type)) {
475 frame_interval = timeperframe->numerator * (u64)USEC_PER_SEC;
476 do_div(frame_interval, timeperframe->denominator);
480 frame_rate = (u64)USEC_PER_SEC;
481 do_div(frame_rate, frame_interval);
483 v4l2_err(&vvd->v4l2_dev,
484 "setting FPS is only possible for the output queue\n");
488 ret = virtio_video_enc_try_framerate(stream, frame_rate);
492 virtio_video_format_fill_default_info(&info, &stream->in_info);
493 info.frame_rate = frame_rate;
495 virtio_video_cmd_set_params(vvd, stream, &info,
496 VIRTIO_VIDEO_QUEUE_TYPE_INPUT);
497 virtio_video_stream_get_params(vvd, stream);
499 out->capability = V4L2_CAP_TIMEPERFRAME;
500 virtio_video_timeperframe_from_info(&stream->in_info, timeperframe);
505 static int virtio_video_enc_s_selection(struct file *file, void *fh,
506 struct v4l2_selection *sel)
508 struct virtio_video_stream *stream = file2stream(file);
509 struct virtio_video_device *vvd = to_virtio_vd(stream->video_dev);
512 if (!V4L2_TYPE_IS_OUTPUT(sel->type))
515 switch (sel->target) {
516 case V4L2_SEL_TGT_CROP:
517 stream->in_info.crop.top = sel->r.top;
518 stream->in_info.crop.left = sel->r.left;
519 stream->in_info.crop.width = sel->r.width;
520 stream->in_info.crop.height = sel->r.height;
526 ret = virtio_video_cmd_set_params(vvd, stream, &stream->in_info,
527 VIRTIO_VIDEO_QUEUE_TYPE_INPUT);
531 return virtio_video_cmd_get_params(vvd, stream,
532 VIRTIO_VIDEO_QUEUE_TYPE_INPUT);
535 static const struct v4l2_ioctl_ops virtio_video_enc_ioctl_ops = {
536 .vidioc_querycap = virtio_video_querycap,
538 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
539 .vidioc_enum_fmt_vid_cap = virtio_video_enc_enum_fmt_vid_cap,
540 .vidioc_enum_fmt_vid_out = virtio_video_enc_enum_fmt_vid_out,
542 .vidioc_enum_fmt_vid_cap_mplane = virtio_video_enc_enum_fmt_vid_cap,
543 .vidioc_enum_fmt_vid_out_mplane = virtio_video_enc_enum_fmt_vid_out,
545 .vidioc_g_fmt_vid_cap_mplane = virtio_video_g_fmt,
546 .vidioc_s_fmt_vid_cap_mplane = virtio_video_enc_s_fmt,
548 .vidioc_g_fmt_vid_out_mplane = virtio_video_g_fmt,
549 .vidioc_s_fmt_vid_out_mplane = virtio_video_enc_s_fmt,
551 .vidioc_try_encoder_cmd = virtio_video_try_encoder_cmd,
552 .vidioc_encoder_cmd = virtio_video_encoder_cmd,
553 .vidioc_enum_frameintervals = virtio_video_enum_framemintervals,
554 .vidioc_enum_framesizes = virtio_video_enum_framesizes,
556 .vidioc_g_selection = virtio_video_g_selection,
557 .vidioc_s_selection = virtio_video_enc_s_selection,
559 .vidioc_reqbufs = virtio_video_reqbufs,
560 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
561 .vidioc_qbuf = virtio_video_qbuf,
562 .vidioc_dqbuf = virtio_video_dqbuf,
563 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
564 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
565 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
567 .vidioc_streamon = v4l2_m2m_ioctl_streamon,
568 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
570 .vidioc_s_parm = virtio_video_enc_s_parm,
571 .vidioc_g_parm = virtio_video_enc_g_parm,
573 .vidioc_subscribe_event = virtio_video_subscribe_event,
574 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
577 void *virtio_video_enc_get_fmt_list(struct virtio_video_device *vvd)
579 return &vvd->output_fmt_list;
582 static struct virtio_video_device_ops virtio_video_enc_ops = {
583 .init_ctrls = virtio_video_enc_init_ctrls,
584 .init_queues = virtio_video_enc_init_queues,
585 .get_fmt_list = virtio_video_enc_get_fmt_list,
588 int virtio_video_enc_init(struct virtio_video_device *vvd)
591 struct video_device *vd = &vvd->video_dev;
593 vd->ioctl_ops = &virtio_video_enc_ioctl_ops;
594 vvd->ops = &virtio_video_enc_ops;
596 num = strscpy(vd->name, "stateful-encoder", sizeof(vd->name));