mirror of
https://github.com/torvalds/linux.git
synced 2024-11-18 10:01:43 +00:00
media: Introduce helpers to fill pixel format structs
Add two new API helpers, v4l2_fill_pixfmt and v4l2_fill_pixfmt_mp, to be used by drivers to calculate plane sizes and bytes per lines. Note that driver-specific padding and alignment are not taken into account, and must be done by drivers using this API. Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
parent
9fb10beb8a
commit
f44b969aa3
@ -445,3 +445,167 @@ int v4l2_s_parm_cap(struct video_device *vdev,
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(v4l2_s_parm_cap);
|
||||
|
||||
const struct v4l2_format_info *v4l2_format_info(u32 format)
|
||||
{
|
||||
static const struct v4l2_format_info formats[] = {
|
||||
/* RGB formats */
|
||||
{ .format = V4L2_PIX_FMT_BGR24, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_RGB24, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_HSV24, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_BGR32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_XBGR32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_RGB32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_XRGB32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_HSV32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_ARGB32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_ABGR32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_GREY, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
|
||||
/* YUV packed formats */
|
||||
{ .format = V4L2_PIX_FMT_YUYV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_YVYU, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_UYVY, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_VYUY, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
|
||||
|
||||
/* YUV planar formats */
|
||||
{ .format = V4L2_PIX_FMT_NV12, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
|
||||
{ .format = V4L2_PIX_FMT_NV21, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
|
||||
{ .format = V4L2_PIX_FMT_NV16, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_NV61, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_NV24, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_NV42, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
|
||||
{ .format = V4L2_PIX_FMT_YUV410, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 },
|
||||
{ .format = V4L2_PIX_FMT_YVU410, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 },
|
||||
{ .format = V4L2_PIX_FMT_YUV411P, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_YUV420, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 },
|
||||
{ .format = V4L2_PIX_FMT_YVU420, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 },
|
||||
{ .format = V4L2_PIX_FMT_YUV422P, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 },
|
||||
|
||||
/* YUV planar formats, non contiguous variant */
|
||||
{ .format = V4L2_PIX_FMT_YUV420M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 },
|
||||
{ .format = V4L2_PIX_FMT_YVU420M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 },
|
||||
{ .format = V4L2_PIX_FMT_YUV422M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_YVU422M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_YUV444M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_YVU444M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 },
|
||||
|
||||
{ .format = V4L2_PIX_FMT_NV12M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
|
||||
{ .format = V4L2_PIX_FMT_NV21M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
|
||||
{ .format = V4L2_PIX_FMT_NV16M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
|
||||
{ .format = V4L2_PIX_FMT_NV61M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(formats); ++i)
|
||||
if (formats[i].format == format)
|
||||
return &formats[i];
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(v4l2_format_info);
|
||||
|
||||
static inline unsigned int v4l2_format_block_width(const struct v4l2_format_info *info, int plane)
|
||||
{
|
||||
if (!info->block_w[plane])
|
||||
return 1;
|
||||
return info->block_w[plane];
|
||||
}
|
||||
|
||||
static inline unsigned int v4l2_format_block_height(const struct v4l2_format_info *info, int plane)
|
||||
{
|
||||
if (!info->block_h[plane])
|
||||
return 1;
|
||||
return info->block_h[plane];
|
||||
}
|
||||
|
||||
int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt,
|
||||
int pixelformat, int width, int height)
|
||||
{
|
||||
const struct v4l2_format_info *info;
|
||||
struct v4l2_plane_pix_format *plane;
|
||||
int i;
|
||||
|
||||
info = v4l2_format_info(pixelformat);
|
||||
if (!info)
|
||||
return -EINVAL;
|
||||
|
||||
pixfmt->width = width;
|
||||
pixfmt->height = height;
|
||||
pixfmt->pixelformat = pixelformat;
|
||||
pixfmt->num_planes = info->mem_planes;
|
||||
|
||||
if (info->mem_planes == 1) {
|
||||
plane = &pixfmt->plane_fmt[0];
|
||||
plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0];
|
||||
plane->sizeimage = 0;
|
||||
|
||||
for (i = 0; i < info->comp_planes; i++) {
|
||||
unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
|
||||
unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
|
||||
unsigned int aligned_width;
|
||||
unsigned int aligned_height;
|
||||
|
||||
aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
|
||||
aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
|
||||
|
||||
plane->sizeimage += info->bpp[i] *
|
||||
DIV_ROUND_UP(aligned_width, hdiv) *
|
||||
DIV_ROUND_UP(aligned_height, vdiv);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < info->comp_planes; i++) {
|
||||
unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
|
||||
unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
|
||||
unsigned int aligned_width;
|
||||
unsigned int aligned_height;
|
||||
|
||||
aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
|
||||
aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
|
||||
|
||||
plane = &pixfmt->plane_fmt[i];
|
||||
plane->bytesperline =
|
||||
info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv);
|
||||
plane->sizeimage =
|
||||
plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt_mp);
|
||||
|
||||
int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, int pixelformat, int width, int height)
|
||||
{
|
||||
const struct v4l2_format_info *info;
|
||||
int i;
|
||||
|
||||
info = v4l2_format_info(pixelformat);
|
||||
if (!info)
|
||||
return -EINVAL;
|
||||
|
||||
/* Single planar API cannot be used for multi plane formats. */
|
||||
if (info->mem_planes > 1)
|
||||
return -EINVAL;
|
||||
|
||||
pixfmt->width = width;
|
||||
pixfmt->height = height;
|
||||
pixfmt->pixelformat = pixelformat;
|
||||
pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0];
|
||||
pixfmt->sizeimage = 0;
|
||||
|
||||
for (i = 0; i < info->comp_planes; i++) {
|
||||
unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
|
||||
unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
|
||||
unsigned int aligned_width;
|
||||
unsigned int aligned_height;
|
||||
|
||||
aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
|
||||
aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
|
||||
|
||||
pixfmt->sizeimage += info->bpp[i] *
|
||||
DIV_ROUND_UP(aligned_width, hdiv) *
|
||||
DIV_ROUND_UP(aligned_height, vdiv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt);
|
||||
|
@ -392,4 +392,37 @@ int v4l2_s_parm_cap(struct video_device *vdev,
|
||||
((u64)(a).numerator * (b).denominator OP \
|
||||
(u64)(b).numerator * (a).denominator)
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Pixel format and FourCC helpers */
|
||||
|
||||
/**
|
||||
* struct v4l2_format_info - information about a V4L2 format
|
||||
* @format: 4CC format identifier (V4L2_PIX_FMT_*)
|
||||
* @mem_planes: Number of memory planes, which includes the alpha plane (1 to 4).
|
||||
* @comp_planes: Number of component planes, which includes the alpha plane (1 to 4).
|
||||
* @bpp: Array of per-plane bytes per pixel
|
||||
* @hdiv: Horizontal chroma subsampling factor
|
||||
* @vdiv: Vertical chroma subsampling factor
|
||||
* @block_w: Per-plane macroblock pixel width (optional)
|
||||
* @block_h: Per-plane macroblock pixel height (optional)
|
||||
*/
|
||||
struct v4l2_format_info {
|
||||
u32 format;
|
||||
u8 mem_planes;
|
||||
u8 comp_planes;
|
||||
u8 bpp[4];
|
||||
u8 hdiv;
|
||||
u8 vdiv;
|
||||
u8 block_w[4];
|
||||
u8 block_h[4];
|
||||
};
|
||||
|
||||
const struct v4l2_format_info *v4l2_format_info(u32 format);
|
||||
|
||||
int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, int pixelformat,
|
||||
int width, int height);
|
||||
int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, int pixelformat,
|
||||
int width, int height);
|
||||
|
||||
#endif /* V4L2_COMMON_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user