diff options
author | Paul Kocialkowski | 2024-09-03 19:14:06 +0200 |
---|---|---|
committer | Paul Kocialkowski | 2024-09-03 19:14:06 +0200 |
commit | 5acc2f557495298391ee585237dfe2fd69b5024e (patch) | |
tree | f9f56f42e166b98150b134624b1248bcf1a54992 | |
parent | c193c161a59e7e890074e2f4934ee133f77af5e4 (diff) |
media: cedrus: Rework subsampling handling to allow 4:2:2 destinations
This reworks subsampling handling to allow decoding 4:2:2 (and 4:4:4)
JPEG without downsampling to 4:2:0. The configured destination pixel
format is checked to support the coded subsampling and downsampling is
only applied for 4:2:0 destination pixel formats.
The JPEG subsampling information is obtained from the structure
returned by the common helper instead of a custom switch/case.
Note that the so-called 422T subsampling (also known as 440) is dropped
from the list since the common helper does not support it and will
error out when encoutering it anyway.
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
-rw-r--r-- | drivers/staging/media/sunxi/cedrus/cedrus_jpeg.c | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_jpeg.c b/drivers/staging/media/sunxi/cedrus/cedrus_jpeg.c index d705e1d6623c..b7b336bcf7a3 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_jpeg.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_jpeg.c @@ -176,7 +176,9 @@ static int cedrus_jpeg_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) .quantization_tables = quantization_tables, .huffman_tables = huffman_tables, }; + const struct v4l2_format_info *format_info; u32 reg, subsampling; + bool downsample = false; unsigned long size; int ret, index; u8 hmax, vmax; @@ -184,34 +186,52 @@ static int cedrus_jpeg_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) size = vb2_get_plane_payload(src_buf, 0); components = header.frame.component; + format_info = v4l2_format_info(ctx->dst_fmt.pixelformat); + if (!format_info) + return -EINVAL; + ret = v4l2_jpeg_parse_header(vb2_plane_vaddr(src_buf, 0), size, &header); if (ret < 0) { v4l2_err(&dev->v4l2_dev, "failed to parse JPEG header: %d\n", ret); return -EINVAL; } - index = components[0].horizontal_sampling_factor << 20 | - components[0].vertical_sampling_factor << 16 | - components[1].horizontal_sampling_factor << 12 | - components[1].vertical_sampling_factor << 8 | - components[2].horizontal_sampling_factor << 4 | - components[2].vertical_sampling_factor; + switch (header.frame.subsampling) { + case V4L2_JPEG_CHROMA_SUBSAMPLING_420: + if (format_info->hdiv != 2 || format_info->vdiv != 2) { + v4l2_err(&dev->v4l2_dev, + "invalid JPEG 4:2:0 subsampling for destination format\n"); + return -EINVAL; + } - switch (index) { - case 0x221111: subsampling = VE_DEC_MPEG_TRIGGER_CHROMA_FMT_420; break; - case 0x211111: + case V4L2_JPEG_CHROMA_SUBSAMPLING_422: + /* Only allow 4:2:2 or 4:2:0 formats. */ + if (format_info->hdiv == 2 && format_info->vdiv == 2) { + downsample = true; + } else if (format_info->hdiv != 2 || format_info->vdiv != 1) { + v4l2_err(&dev->v4l2_dev, + "invalid JPEG 4:2:2 subsampling for destination format\n"); + return -EINVAL; + } + subsampling = VE_DEC_MPEG_TRIGGER_CHROMA_FMT_422; break; - case 0x111111: + case V4L2_JPEG_CHROMA_SUBSAMPLING_444: + /* Only allow 4:4:4 or 4:2:0 formats. */ + if (format_info->hdiv == 2 && format_info->vdiv == 2) { + downsample = true; + } else if (format_info->hdiv != 1 || format_info->vdiv != 1) { + v4l2_err(&dev->v4l2_dev, + "invalid JPEG 4:4:4 subsampling for destination format\n"); + return -EINVAL; + } + subsampling = VE_DEC_MPEG_TRIGGER_CHROMA_FMT_444; break; - case 0x121111: - subsampling = VE_DEC_MPEG_TRIGGER_CHROMA_FMT_422T; - break; default: - v4l2_err(&dev->v4l2_dev, "unsupported subsampling\n"); + v4l2_err(&dev->v4l2_dev, "unsupported JPEG subsampling\n"); return -EINVAL; } @@ -295,11 +315,8 @@ static int cedrus_jpeg_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) /* Enable appropriate interrupts and components. */ reg = VE_DEC_MPEG_CTRL_IRQ_MASK; - if (subsampling == VE_DEC_MPEG_TRIGGER_CHROMA_FMT_422 || - subsampling == VE_DEC_MPEG_TRIGGER_CHROMA_FMT_422T || - subsampling == VE_DEC_MPEG_TRIGGER_CHROMA_FMT_444) + if (downsample) reg |= VE_DEC_MPEG_CTRL_JPEG_FORCE_420; - cedrus_write(dev, VE_DEC_MPEG_CTRL, reg); return 0; |