summaryrefslogtreecommitdiffstats
path: root/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_helpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_helpers.c')
-rw-r--r--meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_helpers.c289
1 files changed, 289 insertions, 0 deletions
diff --git a/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_helpers.c b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_helpers.c
new file mode 100644
index 00000000..ac487053
--- /dev/null
+++ b/meta-egvirt/recipes-kernel/kernel-module-virtio-video/files/virtio_video_helpers.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Driver for virtio video device.
+ *
+ * Copyright 2020 OpenSynergy GmbH.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "virtio_video.h"
+
+struct virtio_video_convert_table {
+ uint32_t virtio_value;
+ uint32_t v4l2_value;
+};
+
+static struct virtio_video_convert_table level_table[] = {
+ { VIRTIO_VIDEO_LEVEL_H264_1_0, V4L2_MPEG_VIDEO_H264_LEVEL_1_0 },
+ { VIRTIO_VIDEO_LEVEL_H264_1_1, V4L2_MPEG_VIDEO_H264_LEVEL_1_1 },
+ { VIRTIO_VIDEO_LEVEL_H264_1_2, V4L2_MPEG_VIDEO_H264_LEVEL_1_2 },
+ { VIRTIO_VIDEO_LEVEL_H264_1_3, V4L2_MPEG_VIDEO_H264_LEVEL_1_3 },
+ { VIRTIO_VIDEO_LEVEL_H264_2_0, V4L2_MPEG_VIDEO_H264_LEVEL_2_0 },
+ { VIRTIO_VIDEO_LEVEL_H264_2_1, V4L2_MPEG_VIDEO_H264_LEVEL_2_1 },
+ { VIRTIO_VIDEO_LEVEL_H264_2_2, V4L2_MPEG_VIDEO_H264_LEVEL_2_2 },
+ { VIRTIO_VIDEO_LEVEL_H264_3_0, V4L2_MPEG_VIDEO_H264_LEVEL_3_0 },
+ { VIRTIO_VIDEO_LEVEL_H264_3_1, V4L2_MPEG_VIDEO_H264_LEVEL_3_1 },
+ { VIRTIO_VIDEO_LEVEL_H264_3_2, V4L2_MPEG_VIDEO_H264_LEVEL_3_2 },
+ { VIRTIO_VIDEO_LEVEL_H264_4_0, V4L2_MPEG_VIDEO_H264_LEVEL_4_0 },
+ { VIRTIO_VIDEO_LEVEL_H264_4_1, V4L2_MPEG_VIDEO_H264_LEVEL_4_1 },
+ { VIRTIO_VIDEO_LEVEL_H264_4_2, V4L2_MPEG_VIDEO_H264_LEVEL_4_2 },
+ { VIRTIO_VIDEO_LEVEL_H264_5_0, V4L2_MPEG_VIDEO_H264_LEVEL_5_0 },
+ { VIRTIO_VIDEO_LEVEL_H264_5_1, V4L2_MPEG_VIDEO_H264_LEVEL_5_1 },
+ { 0 },
+};
+
+uint32_t virtio_video_level_to_v4l2(uint32_t level)
+{
+ size_t idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(level_table); idx++) {
+ if (level_table[idx].virtio_value == level)
+ return level_table[idx].v4l2_value;
+ }
+
+ return 0;
+}
+
+uint32_t virtio_video_v4l2_level_to_virtio(uint32_t v4l2_level)
+{
+ size_t idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(level_table); idx++) {
+ if (level_table[idx].v4l2_value == v4l2_level)
+ return level_table[idx].virtio_value;
+ }
+
+ return 0;
+}
+
+static struct virtio_video_convert_table profile_table[] = {
+ { VIRTIO_VIDEO_PROFILE_H264_BASELINE,
+ V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE },
+ { VIRTIO_VIDEO_PROFILE_H264_MAIN, V4L2_MPEG_VIDEO_H264_PROFILE_MAIN },
+ { VIRTIO_VIDEO_PROFILE_H264_EXTENDED,
+ V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED },
+ { VIRTIO_VIDEO_PROFILE_H264_HIGH, V4L2_MPEG_VIDEO_H264_PROFILE_HIGH },
+ { VIRTIO_VIDEO_PROFILE_H264_HIGH10PROFILE,
+ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10 },
+ { VIRTIO_VIDEO_PROFILE_H264_HIGH422PROFILE,
+ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422},
+ { VIRTIO_VIDEO_PROFILE_H264_HIGH444PREDICTIVEPROFILE,
+ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE },
+ { VIRTIO_VIDEO_PROFILE_H264_SCALABLEBASELINE,
+ V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE },
+ { VIRTIO_VIDEO_PROFILE_H264_SCALABLEHIGH,
+ V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH },
+ { VIRTIO_VIDEO_PROFILE_H264_STEREOHIGH,
+ V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH },
+ { VIRTIO_VIDEO_PROFILE_H264_MULTIVIEWHIGH,
+ V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH },
+ { 0 },
+};
+
+uint32_t virtio_video_profile_to_v4l2(uint32_t profile)
+{
+ size_t idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(profile_table); idx++) {
+ if (profile_table[idx].virtio_value == profile)
+ return profile_table[idx].v4l2_value;
+ }
+
+ return 0;
+}
+
+uint32_t virtio_video_v4l2_profile_to_virtio(uint32_t v4l2_profile)
+{
+ size_t idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(profile_table); idx++) {
+ if (profile_table[idx].v4l2_value == v4l2_profile)
+ return profile_table[idx].virtio_value;
+ }
+
+ return 0;
+}
+
+static struct virtio_video_convert_table format_table[] = {
+ { VIRTIO_VIDEO_FORMAT_ARGB8888, V4L2_PIX_FMT_ARGB32 },
+ { VIRTIO_VIDEO_FORMAT_BGRA8888, V4L2_PIX_FMT_ABGR32 },
+ { VIRTIO_VIDEO_FORMAT_RGBA8888, V4L2_PIX_FMT_RGB32 },
+ { VIRTIO_VIDEO_FORMAT_NV12, V4L2_PIX_FMT_NV12 },
+ { VIRTIO_VIDEO_FORMAT_YUV420, V4L2_PIX_FMT_YUV420 },
+ { VIRTIO_VIDEO_FORMAT_YVU420, V4L2_PIX_FMT_YVU420 },
+ { VIRTIO_VIDEO_FORMAT_YUV422, V4L2_PIX_FMT_YUYV },
+ { VIRTIO_VIDEO_FORMAT_MPEG2, V4L2_PIX_FMT_MPEG2 },
+ { VIRTIO_VIDEO_FORMAT_MPEG4, V4L2_PIX_FMT_MPEG4 },
+ { VIRTIO_VIDEO_FORMAT_H264, V4L2_PIX_FMT_H264 },
+ { VIRTIO_VIDEO_FORMAT_HEVC, V4L2_PIX_FMT_HEVC },
+ { VIRTIO_VIDEO_FORMAT_VP8, V4L2_PIX_FMT_VP8 },
+ { VIRTIO_VIDEO_FORMAT_VP9, V4L2_PIX_FMT_VP9 },
+ { 0 },
+};
+
+uint32_t virtio_video_format_to_v4l2(uint32_t format)
+{
+ size_t idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(format_table); idx++) {
+ if (format_table[idx].virtio_value == format)
+ return format_table[idx].v4l2_value;
+ }
+
+ return 0;
+}
+
+uint32_t virtio_video_v4l2_format_to_virtio(uint32_t v4l2_format)
+{
+ size_t idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(format_table); idx++) {
+ if (format_table[idx].v4l2_value == v4l2_format)
+ return format_table[idx].virtio_value;
+ }
+
+ return 0;
+}
+
+static struct virtio_video_convert_table control_table[] = {
+ { VIRTIO_VIDEO_CONTROL_BITRATE, V4L2_CID_MPEG_VIDEO_BITRATE },
+ { VIRTIO_VIDEO_CONTROL_PROFILE, V4L2_CID_MPEG_VIDEO_H264_PROFILE },
+ { VIRTIO_VIDEO_CONTROL_LEVEL, V4L2_CID_MPEG_VIDEO_H264_LEVEL },
+ { 0 },
+};
+
+uint32_t virtio_video_control_to_v4l2(uint32_t control)
+{
+ size_t idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(control_table); idx++) {
+ if (control_table[idx].virtio_value == control)
+ return control_table[idx].v4l2_value;
+ }
+
+ return 0;
+}
+
+uint32_t virtio_video_v4l2_control_to_virtio(uint32_t v4l2_control)
+{
+ size_t idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(control_table); idx++) {
+ if (control_table[idx].v4l2_value == v4l2_control)
+ return control_table[idx].virtio_value;
+ }
+
+ return 0;
+}
+
+uint32_t virtio_video_get_format_from_virtio_profile(uint32_t virtio_profile)
+{
+ if (virtio_profile >= VIRTIO_VIDEO_PROFILE_H264_MIN &&
+ virtio_profile <= VIRTIO_VIDEO_PROFILE_H264_MAX)
+ return VIRTIO_VIDEO_FORMAT_H264;
+ else if (virtio_profile >= VIRTIO_VIDEO_PROFILE_HEVC_MIN &&
+ virtio_profile <= VIRTIO_VIDEO_PROFILE_HEVC_MAX)
+ return VIRTIO_VIDEO_FORMAT_HEVC;
+ else if (virtio_profile >= VIRTIO_VIDEO_PROFILE_VP8_MIN &&
+ virtio_profile <= VIRTIO_VIDEO_PROFILE_VP8_MAX)
+ return VIRTIO_VIDEO_FORMAT_VP8;
+ else if (virtio_profile >= VIRTIO_VIDEO_PROFILE_VP9_MIN &&
+ virtio_profile <= VIRTIO_VIDEO_PROFILE_VP9_MAX)
+ return VIRTIO_VIDEO_FORMAT_VP9;
+
+ return 0;
+}
+
+struct video_format *virtio_video_find_video_format(struct list_head *fmts_list,
+ uint32_t format)
+{
+ struct video_format *fmt = NULL;
+
+ list_for_each_entry(fmt, fmts_list, formats_list_entry) {
+ if (fmt->desc.format == format)
+ return fmt;
+ }
+
+ return NULL;
+}
+
+void virtio_video_format_from_info(struct video_format_info *info,
+ struct v4l2_pix_format_mplane *pix_mp)
+{
+ int i;
+
+ pix_mp->width = info->frame_width;
+ pix_mp->height = info->frame_height;
+ pix_mp->field = V4L2_FIELD_NONE;
+ pix_mp->colorspace = V4L2_COLORSPACE_REC709;
+ pix_mp->xfer_func = 0;
+ pix_mp->ycbcr_enc = 0;
+ pix_mp->quantization = 0;
+ memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
+ memset(pix_mp->plane_fmt[0].reserved, 0,
+ sizeof(pix_mp->plane_fmt[0].reserved));
+
+ pix_mp->num_planes = info->num_planes;
+ pix_mp->pixelformat = info->fourcc_format;
+
+ for (i = 0; i < info->num_planes; i++) {
+ pix_mp->plane_fmt[i].bytesperline =
+ info->plane_format[i].stride;
+ pix_mp->plane_fmt[i].sizeimage =
+ info->plane_format[i].plane_size;
+ }
+}
+
+void virtio_video_format_fill_default_info(struct video_format_info *dst_info,
+ struct video_format_info *src_info)
+{
+ memcpy(dst_info, src_info, sizeof(*dst_info));
+}
+
+void virtio_video_pix_fmt_sp2mp(const struct v4l2_pix_format *pix,
+ struct v4l2_pix_format_mplane *pix_mp)
+{
+ memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
+ memset(&pix_mp->plane_fmt[0].reserved, 0,
+ sizeof(pix_mp->plane_fmt[0].reserved));
+ pix_mp->num_planes = 1;
+ pix_mp->width = pix->width;
+ pix_mp->height = pix->height;
+ pix_mp->pixelformat = pix->pixelformat;
+ pix_mp->field = pix->field;
+ pix_mp->plane_fmt[0].bytesperline = pix->bytesperline;
+ pix_mp->plane_fmt[0].sizeimage = pix->sizeimage;
+ pix_mp->colorspace = pix->colorspace;
+ pix_mp->flags = pix->flags;
+ pix_mp->ycbcr_enc = pix->ycbcr_enc;
+ pix_mp->quantization = pix->quantization;
+ pix_mp->xfer_func = pix->xfer_func;
+}
+
+void virtio_video_pix_fmt_mp2sp(const struct v4l2_pix_format_mplane *pix_mp,
+ struct v4l2_pix_format *pix)
+{
+ pix->width = pix_mp->width;
+ pix->height = pix_mp->height;
+ pix->pixelformat = pix_mp->pixelformat;
+ pix->field = pix_mp->field;
+ pix->bytesperline = pix_mp->plane_fmt[0].bytesperline;
+ pix->sizeimage = pix_mp->plane_fmt[0].sizeimage;
+ pix->colorspace = pix_mp->colorspace;
+ pix->priv = 0;
+ pix->flags = pix_mp->flags;
+ pix->ycbcr_enc = pix_mp->ycbcr_enc;
+ pix->quantization = pix_mp->quantization;
+ pix->xfer_func = pix_mp->xfer_func;
+}