174 lines
6.1 KiB
Diff
174 lines
6.1 KiB
Diff
From 6c7a2caf88dda1aa4459b80d399da37dff6c6942 Mon Sep 17 00:00:00 2001
|
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
|
Date: Fri, 18 Dec 2020 19:56:31 +0000
|
|
Subject: [PATCH] staging/bcm2835-codec: Add support for decoding
|
|
interlaced streams
|
|
|
|
The video decoder can support decoding interlaced streams, so add
|
|
the required plumbing to signal this correctly.
|
|
|
|
The encoder and ISP do NOT support interlaced data, so trying to
|
|
configure an interlaced format on those nodes will be rejected.
|
|
|
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
|
---
|
|
.../bcm2835-codec/bcm2835-v4l2-codec.c | 84 +++++++++++++++++--
|
|
1 file changed, 77 insertions(+), 7 deletions(-)
|
|
|
|
--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
|
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
|
@@ -619,6 +619,7 @@ struct bcm2835_codec_q_data {
|
|
unsigned int crop_height;
|
|
bool selection_set;
|
|
struct v4l2_fract aspect_ratio;
|
|
+ enum v4l2_field field;
|
|
|
|
unsigned int sizeimage;
|
|
unsigned int sequence;
|
|
@@ -986,6 +987,10 @@ static void handle_fmt_changed(struct bc
|
|
struct bcm2835_codec_q_data *q_data;
|
|
struct mmal_msg_event_format_changed *format =
|
|
(struct mmal_msg_event_format_changed *)mmal_buf->buffer;
|
|
+ struct mmal_parameter_video_interlace_type interlace;
|
|
+ int interlace_size = sizeof(interlace);
|
|
+ int ret;
|
|
+
|
|
v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed: buff size min %u, rec %u, buff num min %u, rec %u\n",
|
|
__func__,
|
|
format->buffer_size_min,
|
|
@@ -1029,6 +1034,30 @@ static void handle_fmt_changed(struct bc
|
|
q_data->aspect_ratio.numerator = format->es.video.par.num;
|
|
q_data->aspect_ratio.denominator = format->es.video.par.den;
|
|
|
|
+ ret = vchiq_mmal_port_parameter_get(ctx->dev->instance,
|
|
+ &ctx->component->output[0],
|
|
+ MMAL_PARAMETER_VIDEO_INTERLACE_TYPE,
|
|
+ &interlace,
|
|
+ &interlace_size);
|
|
+ if (!ret) {
|
|
+ switch (interlace.mode) {
|
|
+ case MMAL_INTERLACE_PROGRESSIVE:
|
|
+ default:
|
|
+ q_data->field = V4L2_FIELD_NONE;
|
|
+ break;
|
|
+ case MMAL_INTERLACE_FIELDS_INTERLEAVED_UPPER_FIRST:
|
|
+ q_data->field = V4L2_FIELD_INTERLACED_TB;
|
|
+ break;
|
|
+ case MMAL_INTERLACE_FIELDS_INTERLEAVED_LOWER_FIRST:
|
|
+ q_data->field = V4L2_FIELD_INTERLACED_BT;
|
|
+ break;
|
|
+ }
|
|
+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: interlace mode %u, v4l2 field %u\n",
|
|
+ __func__, interlace.mode, q_data->field);
|
|
+ } else {
|
|
+ q_data->field = V4L2_FIELD_NONE;
|
|
+ }
|
|
+
|
|
queue_res_chg_event(ctx);
|
|
}
|
|
|
|
@@ -1101,6 +1130,22 @@ static void op_buffer_cb(struct vchiq_mm
|
|
vb2->vb2_buf.timestamp = mmal_buf->pts * 1000;
|
|
|
|
vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
|
|
+ switch (mmal_buf->mmal_flags &
|
|
+ (MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED |
|
|
+ MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST)) {
|
|
+ case 0:
|
|
+ case MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST: /* Bogus */
|
|
+ vb2->field = V4L2_FIELD_NONE;
|
|
+ break;
|
|
+ case MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED:
|
|
+ vb2->field = V4L2_FIELD_INTERLACED_BT;
|
|
+ break;
|
|
+ case (MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED |
|
|
+ MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST):
|
|
+ vb2->field = V4L2_FIELD_INTERLACED_TB;
|
|
+ break;
|
|
+ }
|
|
+
|
|
if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
|
|
vb2->flags |= V4L2_BUF_FLAG_KEYFRAME;
|
|
|
|
@@ -1272,7 +1317,7 @@ static int vidioc_g_fmt(struct bcm2835_c
|
|
f->fmt.pix_mp.width = q_data->crop_width;
|
|
f->fmt.pix_mp.height = q_data->height;
|
|
f->fmt.pix_mp.pixelformat = q_data->fmt->fourcc;
|
|
- f->fmt.pix_mp.field = V4L2_FIELD_NONE;
|
|
+ f->fmt.pix_mp.field = q_data->field;
|
|
f->fmt.pix_mp.colorspace = ctx->colorspace;
|
|
f->fmt.pix_mp.plane_fmt[0].sizeimage = q_data->sizeimage;
|
|
f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->bytesperline;
|
|
@@ -1347,7 +1392,33 @@ static int vidioc_try_fmt(struct bcm2835
|
|
memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
|
|
sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
|
|
|
|
- f->fmt.pix_mp.field = V4L2_FIELD_NONE;
|
|
+ if (ctx->dev->role == DECODE) {
|
|
+ switch (f->fmt.pix_mp.field) {
|
|
+ /*
|
|
+ * All of this is pretty much guesswork as we'll set the
|
|
+ * interlace format correctly come format changed, and signal
|
|
+ * it appropriately on each buffer.
|
|
+ */
|
|
+ default:
|
|
+ case V4L2_FIELD_NONE:
|
|
+ case V4L2_FIELD_ANY:
|
|
+ f->fmt.pix_mp.field = V4L2_FIELD_NONE;
|
|
+ break;
|
|
+ case V4L2_FIELD_INTERLACED:
|
|
+ f->fmt.pix_mp.field = V4L2_FIELD_INTERLACED;
|
|
+ break;
|
|
+ case V4L2_FIELD_TOP:
|
|
+ case V4L2_FIELD_BOTTOM:
|
|
+ case V4L2_FIELD_INTERLACED_TB:
|
|
+ f->fmt.pix_mp.field = V4L2_FIELD_INTERLACED_TB;
|
|
+ break;
|
|
+ case V4L2_FIELD_INTERLACED_BT:
|
|
+ f->fmt.pix_mp.field = V4L2_FIELD_INTERLACED_BT;
|
|
+ break;
|
|
+ }
|
|
+ } else {
|
|
+ f->fmt.pix_mp.field = V4L2_FIELD_NONE;
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
@@ -1430,6 +1501,8 @@ static int vidioc_s_fmt(struct bcm2835_c
|
|
ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
|
|
ctx->quant = f->fmt.pix_mp.quantization;
|
|
|
|
+ q_data->field = f->fmt.pix_mp.field;
|
|
+
|
|
/* All parameters should have been set correctly by try_fmt */
|
|
q_data->bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline;
|
|
q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage;
|
|
@@ -2429,11 +2502,6 @@ static int bcm2835_codec_buf_prepare(str
|
|
if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
|
|
if (vbuf->field == V4L2_FIELD_ANY)
|
|
vbuf->field = V4L2_FIELD_NONE;
|
|
- if (vbuf->field != V4L2_FIELD_NONE) {
|
|
- v4l2_err(&ctx->dev->v4l2_dev, "%s field isn't supported\n",
|
|
- __func__);
|
|
- return -EINVAL;
|
|
- }
|
|
}
|
|
|
|
if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
|
|
@@ -2735,6 +2803,7 @@ static int bcm2835_codec_open(struct fil
|
|
ctx->q_data[V4L2_M2M_SRC].crop_width,
|
|
ctx->q_data[V4L2_M2M_SRC].height,
|
|
ctx->q_data[V4L2_M2M_SRC].fmt);
|
|
+ ctx->q_data[V4L2_M2M_SRC].field = V4L2_FIELD_NONE;
|
|
|
|
ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
|
|
ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
|
|
@@ -2749,6 +2818,7 @@ static int bcm2835_codec_open(struct fil
|
|
ctx->q_data[V4L2_M2M_DST].fmt);
|
|
ctx->q_data[V4L2_M2M_DST].aspect_ratio.numerator = 1;
|
|
ctx->q_data[V4L2_M2M_DST].aspect_ratio.denominator = 1;
|
|
+ ctx->q_data[V4L2_M2M_DST].field = V4L2_FIELD_NONE;
|
|
|
|
ctx->colorspace = V4L2_COLORSPACE_REC709;
|
|
ctx->bitrate = 10 * 1000 * 1000;
|