media: coda: add JPEG downscale support

The JPEG decoder in the CODA960 VPU can downscale images while decoding,
with a factor of 1/2, 1/4, or 1/8.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
Philipp Zabel 2022-04-06 09:51:45 +01:00 committed by Mauro Carvalho Chehab
parent fb11bc40c4
commit 7e32aab9f4
3 changed files with 39 additions and 8 deletions

View file

@ -657,6 +657,8 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
const struct coda_q_data *q_data_src;
const struct coda_codec *codec;
struct vb2_queue *src_vq;
int hscale = 0;
int vscale = 0;
int ret;
bool use_vdoa;
@ -673,8 +675,13 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
*/
src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
if (vb2_is_streaming(src_vq)) {
f->fmt.pix.width = q_data_src->width;
f->fmt.pix.height = q_data_src->height;
if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
ctx->dev->devtype->product == CODA_960) {
hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width);
vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height);
}
f->fmt.pix.width = q_data_src->width >> hscale;
f->fmt.pix.height = q_data_src->height >> vscale;
if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) {
if (ctx->params.jpeg_chroma_subsampling ==
@ -704,8 +711,8 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
/* The decoders always write complete macroblocks or MCUs */
if (ctx->inst_type == CODA_INST_DECODER) {
f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
f->fmt.pix.height = round_up(f->fmt.pix.height, 16);
f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16 >> hscale);
f->fmt.pix.height = round_up(f->fmt.pix.height, 16 >> vscale);
if (codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
@ -850,17 +857,26 @@ static int coda_s_fmt_vid_cap(struct file *file, void *priv,
struct coda_q_data *q_data_src;
const struct coda_codec *codec;
struct v4l2_rect r;
int hscale = 0;
int vscale = 0;
int ret;
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
ctx->dev->devtype->product == CODA_960) {
hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width);
vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height);
}
ret = coda_try_fmt_vid_cap(file, priv, f);
if (ret)
return ret;
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
r.left = 0;
r.top = 0;
r.width = q_data_src->width;
r.height = q_data_src->height;
r.width = q_data_src->width >> hscale;
r.height = q_data_src->height >> vscale;
ret = coda_s_fmt(ctx, f, &r);
if (ret)

View file

@ -1328,6 +1328,7 @@ static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx)
struct coda_q_data *q_data_src, *q_data_dst;
struct vb2_v4l2_buffer *src_buf, *dst_buf;
int chroma_interleave;
int scl_hor_mode, scl_ver_mode;
src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
@ -1335,6 +1336,9 @@ static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx)
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
dst_fourcc = q_data_dst->fourcc;
scl_hor_mode = coda_jpeg_scale(q_data_src->width, q_data_dst->width);
scl_ver_mode = coda_jpeg_scale(q_data_src->height, q_data_dst->height);
if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0)
vb2_set_plane_payload(&src_buf->vb2_buf, 0,
vb2_plane_size(&src_buf->vb2_buf, 0));
@ -1383,7 +1387,11 @@ static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx)
coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO);
coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO);
coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO);
coda_write(dev, 0, CODA9_REG_JPEG_SCL_INFO);
if (scl_hor_mode || scl_ver_mode)
val = CODA9_JPEG_SCL_ENABLE | (scl_hor_mode << 2) | scl_ver_mode;
else
val = 0;
coda_write(dev, val, CODA9_REG_JPEG_SCL_INFO);
coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG);
coda_write(dev, ctx->params.jpeg_restart_interval,
CODA9_REG_JPEG_RST_INTVAL);

View file

@ -380,6 +380,13 @@ u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size);
void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc,
u8 level_idc);
static inline int coda_jpeg_scale(int src, int dst)
{
return (dst <= src / 8) ? 3 :
(dst <= src / 4) ? 2 :
(dst <= src / 2) ? 1 : 0;
}
bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb);
int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb);
int coda_jpeg_write_tables(struct coda_ctx *ctx);