Skip to content

Commit

Permalink
media: hevc_dec: Add in downstream single planar SAND variant
Browse files Browse the repository at this point in the history
Upstream will take the multi-planar SAND format, but add back
in the downstream single planar variant for backwards compatibility

Signed-off-by: Dave Stevenson <[email protected]>
  • Loading branch information
6by9 committed Dec 6, 2024
1 parent 98cf2f8 commit 3406809
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 46 deletions.
97 changes: 71 additions & 26 deletions drivers/media/platform/raspberrypi/hevc_dec/hevc_d_h265.c
Original file line number Diff line number Diff line change
Expand Up @@ -1748,12 +1748,26 @@ static void hevc_d_h265_setup(struct hevc_d_ctx *ctx, struct hevc_d_run *run)
de->bit_copy_gptr = ctx->bitbufs + ctx->p1idx;
de->bit_copy_len = 0;

de->luma_stride = ctx->dst_fmt.height * 128;
de->frame_luma_addr =
vb2_dma_contig_plane_dma_addr(&run->dst->vb2_buf, 0);
de->chroma_stride = de->luma_stride / 2;
de->frame_chroma_addr =
vb2_dma_contig_plane_dma_addr(&run->dst->vb2_buf, 1);
switch (ctx->dst_fmt.pixelformat) {
case V4L2_PIX_FMT_NV12_COL128M:
case V4L2_PIX_FMT_NV12_10_COL128M:
de->luma_stride = ctx->dst_fmt.height * 128;
de->frame_luma_addr =
vb2_dma_contig_plane_dma_addr(&run->dst->vb2_buf, 0);
de->chroma_stride = de->luma_stride / 2;
de->frame_chroma_addr =
vb2_dma_contig_plane_dma_addr(&run->dst->vb2_buf, 1);
break;
case V4L2_PIX_FMT_NV12_COL128:
case V4L2_PIX_FMT_NV12_10_COL128:
de->luma_stride = ctx->dst_fmt.plane_fmt[0].bytesperline * 128;
de->frame_luma_addr =
vb2_dma_contig_plane_dma_addr(&run->dst->vb2_buf, 0);
de->chroma_stride = de->luma_stride;
de->frame_chroma_addr = de->frame_luma_addr +
(ctx->dst_fmt.height * 128);
break;
}
de->frame_aux = NULL;

if (s->sps.bit_depth_luma_minus8 !=
Expand All @@ -1766,15 +1780,19 @@ static void hevc_d_h265_setup(struct hevc_d_ctx *ctx, struct hevc_d_run *run)
}
if (s->sps.bit_depth_luma_minus8 == 0) {
if (ctx->dst_fmt.pixelformat !=
V4L2_PIX_FMT_NV12_COL128M) {
V4L2_PIX_FMT_NV12_COL128M &&
ctx->dst_fmt.pixelformat !=
V4L2_PIX_FMT_NV12_COL128) {
v4l2_err(&dev->v4l2_dev,
"Pixel format %#x != NV12_COL128M for 8-bit output",
ctx->dst_fmt.pixelformat);
goto fail;
}
} else if (s->sps.bit_depth_luma_minus8 == 2) {
if (ctx->dst_fmt.pixelformat !=
V4L2_PIX_FMT_NV12_10_COL128M) {
V4L2_PIX_FMT_NV12_10_COL128M &&
ctx->dst_fmt.pixelformat !=
V4L2_PIX_FMT_NV12_10_COL128) {
v4l2_err(&dev->v4l2_dev,
"Pixel format %#x != NV12_10_COL128M for 10-bit output",
ctx->dst_fmt.pixelformat);
Expand All @@ -1786,20 +1804,40 @@ static void hevc_d_h265_setup(struct hevc_d_ctx *ctx, struct hevc_d_run *run)
s->sps.bit_depth_luma_minus8 + 8);
goto fail;
}
if (run->dst->vb2_buf.num_planes != 2) {
v4l2_warn(&dev->v4l2_dev, "Capture planes (%d) != 2\n",
run->dst->vb2_buf.num_planes);
goto fail;
}
if (run->dst->planes[0].length < ctx->dst_fmt.plane_fmt[0].sizeimage ||
run->dst->planes[1].length < ctx->dst_fmt.plane_fmt[1].sizeimage) {
v4l2_warn(&dev->v4l2_dev,
"Capture planes length (%d/%d) < sizeimage (%d/%d)\n",
run->dst->planes[0].length,
run->dst->planes[1].length,
ctx->dst_fmt.plane_fmt[0].sizeimage,
ctx->dst_fmt.plane_fmt[1].sizeimage);
goto fail;
switch (ctx->dst_fmt.pixelformat) {
case V4L2_PIX_FMT_NV12_COL128M:
case V4L2_PIX_FMT_NV12_10_COL128M:
if (run->dst->vb2_buf.num_planes != 2) {
v4l2_warn(&dev->v4l2_dev, "Capture planes (%d) != 2\n",
run->dst->vb2_buf.num_planes);
goto fail;
}
if (run->dst->planes[0].length < ctx->dst_fmt.plane_fmt[0].sizeimage ||
run->dst->planes[1].length < ctx->dst_fmt.plane_fmt[1].sizeimage) {
v4l2_warn(&dev->v4l2_dev,
"Capture planes length (%d/%d) < sizeimage (%d/%d)\n",
run->dst->planes[0].length,
run->dst->planes[1].length,
ctx->dst_fmt.plane_fmt[0].sizeimage,
ctx->dst_fmt.plane_fmt[1].sizeimage);
goto fail;
}
break;
case V4L2_PIX_FMT_NV12_COL128:
case V4L2_PIX_FMT_NV12_10_COL128:
if (run->dst->vb2_buf.num_planes != 1) {
v4l2_warn(&dev->v4l2_dev, "Capture planes (%d) != 1\n",
run->dst->vb2_buf.num_planes);
goto fail;
}
if (run->dst->planes[0].length < ctx->dst_fmt.plane_fmt[0].sizeimage) {
v4l2_warn(&dev->v4l2_dev,
"Capture planes length (%d) < sizeimage (%d)\n",
run->dst->planes[0].length,
ctx->dst_fmt.plane_fmt[0].sizeimage);
goto fail;
}
break;
}

/*
Expand Down Expand Up @@ -1993,8 +2031,13 @@ static void hevc_d_h265_setup(struct hevc_d_ctx *ctx, struct hevc_d_run *run)

de->ref_addrs[i][0] =
vb2_dma_contig_plane_dma_addr(buf, 0);
de->ref_addrs[i][1] =
vb2_dma_contig_plane_dma_addr(buf, 1);
if (ctx->dst_fmt.pixelformat == V4L2_PIX_FMT_NV12_COL128M ||
ctx->dst_fmt.pixelformat == V4L2_PIX_FMT_NV12_10_COL128M)
de->ref_addrs[i][1] =
vb2_dma_contig_plane_dma_addr(buf, 1);
else
de->ref_addrs[i][1] = de->ref_addrs[i][0] +
(ctx->dst_fmt.height * 128);
}

/* Move DPB from temp */
Expand Down Expand Up @@ -2629,9 +2672,11 @@ static int try_ctrl_sps(struct v4l2_ctrl *ctrl)
return 0;

if ((sps->bit_depth_luma_minus8 == 0 &&
ctx->dst_fmt.pixelformat != V4L2_PIX_FMT_NV12_COL128M) ||
ctx->dst_fmt.pixelformat != V4L2_PIX_FMT_NV12_COL128M &&
ctx->dst_fmt.pixelformat != V4L2_PIX_FMT_NV12_COL128) ||
(sps->bit_depth_luma_minus8 == 2 &&
ctx->dst_fmt.pixelformat != V4L2_PIX_FMT_NV12_10_COL128M)) {
ctx->dst_fmt.pixelformat != V4L2_PIX_FMT_NV12_10_COL128M &&
ctx->dst_fmt.pixelformat != V4L2_PIX_FMT_NV12_10_COL128)) {
v4l2_warn(&dev->v4l2_dev,
"SPS luma depth %d does not match capture format\n",
sps->bit_depth_luma_minus8 + 8);
Expand Down
102 changes: 82 additions & 20 deletions drivers/media/platform/raspberrypi/hevc_dec/hevc_d_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,17 +150,57 @@ static void hevc_d_prepare_dst_format(struct v4l2_pix_format_mplane *pix_fmt)
bytesperline = width * 4 / 3;
sizeimage = bytesperline * height;
break;

case V4L2_PIX_FMT_NV12_COL128:
/* Width rounds up to columns */
width = ALIGN(width, 128);
height = ALIGN(height, 8);

/* column height
* Accept suggested shape if at least min & < 2 * min
*/
bytesperline = constrain2x(bytesperline, height * 3 / 2);
sizeimage = bytesperline * width;
break;

case V4L2_PIX_FMT_NV12_10_COL128:
/* width in pixels (3 pels = 4 bytes) rounded to 128 byte
* columns
*/
width = ALIGN(((width + 2) / 3), 32) * 3;
height = ALIGN(height, 8);

/* column height
* Accept suggested shape if at least min & < 2 * min
*/
bytesperline = constrain2x(bytesperline, height * 3 / 2);
sizeimage = bytesperline * width * 4 / 3;
break;

}

pix_fmt->width = width;
pix_fmt->height = height;

pix_fmt->field = V4L2_FIELD_NONE;
pix_fmt->plane_fmt[0].bytesperline = bytesperline;
pix_fmt->plane_fmt[0].sizeimage = sizeimage;
pix_fmt->plane_fmt[1].bytesperline = bytesperline;
pix_fmt->plane_fmt[1].sizeimage = sizeimage / 2;
pix_fmt->num_planes = 2;

switch (pix_fmt->pixelformat) {
default:
case V4L2_PIX_FMT_NV12_COL128M:
case V4L2_PIX_FMT_NV12_10_COL128M:
pix_fmt->plane_fmt[0].bytesperline = bytesperline;
pix_fmt->plane_fmt[0].sizeimage = sizeimage;
pix_fmt->plane_fmt[1].bytesperline = bytesperline;
pix_fmt->plane_fmt[1].sizeimage = sizeimage / 2;
pix_fmt->num_planes = 2;
break;
case V4L2_PIX_FMT_NV12_COL128:
case V4L2_PIX_FMT_NV12_10_COL128:
pix_fmt->plane_fmt[0].bytesperline = bytesperline;
pix_fmt->plane_fmt[0].sizeimage = sizeimage;
pix_fmt->num_planes = 1;
break;
}
}

static int hevc_d_querycap(struct file *file, void *priv,
Expand Down Expand Up @@ -245,19 +285,30 @@ static int hevc_d_hevc_validate_sps(const struct v4l2_ctrl_hevc_sps * const sps)
static u32 pixelformat_from_sps(const struct v4l2_ctrl_hevc_sps * const sps,
const int index)
{
static const u32 all_formats[] = {
V4L2_PIX_FMT_NV12_COL128M,
V4L2_PIX_FMT_NV12_10_COL128M,
V4L2_PIX_FMT_NV12_COL128,
V4L2_PIX_FMT_NV12_10_COL128,
};
u32 pf = 0;

if (!is_sps_set(sps) || !hevc_d_hevc_validate_sps(sps)) {
/* Treat this as an error? For now return both */
if (index == 0)
pf = V4L2_PIX_FMT_NV12_COL128M;
else if (index == 1)
pf = V4L2_PIX_FMT_NV12_10_COL128M;
} else if (index == 0) {
if (sps->bit_depth_luma_minus8 == 0)
pf = V4L2_PIX_FMT_NV12_COL128M;
else if (sps->bit_depth_luma_minus8 == 2)
pf = V4L2_PIX_FMT_NV12_10_COL128M;
if (index < ARRAY_SIZE(all_formats))
pf = all_formats[index];
} else {
if (index == 0) {
if (sps->bit_depth_luma_minus8 == 0)
pf = V4L2_PIX_FMT_NV12_COL128M;
else if (sps->bit_depth_luma_minus8 == 2)
pf = V4L2_PIX_FMT_NV12_10_COL128M;
} else if (index == 1) {
if (sps->bit_depth_luma_minus8 == 0)
pf = V4L2_PIX_FMT_NV12_COL128;
else if (sps->bit_depth_luma_minus8 == 2)
pf = V4L2_PIX_FMT_NV12_10_COL128;
}
}

return pf;
Expand Down Expand Up @@ -466,17 +517,28 @@ static int hevc_d_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
pix_fmt = get_dst_fmt(ctx);

if (*nplanes) {
if (*nplanes < 2 ||
sizes[0] < pix_fmt->plane_fmt[0].sizeimage ||
sizes[1] < pix_fmt->plane_fmt[1].sizeimage)
return -EINVAL;
if (pix_fmt->pixelformat == V4L2_PIX_FMT_NV12_COL128M ||
pix_fmt->pixelformat == V4L2_PIX_FMT_NV12_10_COL128M) {
if (*nplanes < 2 ||
sizes[0] < pix_fmt->plane_fmt[0].sizeimage ||
sizes[1] < pix_fmt->plane_fmt[1].sizeimage)
return -EINVAL;
} else {
if (sizes[0] < pix_fmt->plane_fmt[0].sizeimage)
return -EINVAL;
}
} else {
sizes[0] = pix_fmt->plane_fmt[0].sizeimage;
if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
*nplanes = 1;
} else {
sizes[1] = pix_fmt->plane_fmt[1].sizeimage;
*nplanes = 2;
if (pix_fmt->pixelformat == V4L2_PIX_FMT_NV12_COL128M ||
pix_fmt->pixelformat == V4L2_PIX_FMT_NV12_10_COL128M) {
sizes[1] = pix_fmt->plane_fmt[1].sizeimage;
*nplanes = 2;
} else {
*nplanes = 1;
}
}
}

Expand Down

0 comments on commit 3406809

Please sign in to comment.