diff options
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.c | 289 |
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; +} |