mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-08-01 15:07:49 +00:00
Allwinner: Update cedrus patches
This commit is contained in:
parent
eebc912afa
commit
168d2244cd
@ -1,20 +1,20 @@
|
||||
From d117460aed81ee5cd384045a1189c9de758d17c6 Mon Sep 17 00:00:00 2001
|
||||
From 60808cc1810d47f91c368de8ffb7db59cabceaf9 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Tue, 28 May 2019 21:05:34 +0200
|
||||
Subject: [PATCH] 10-bit HEVC hack
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
drivers/staging/media/sunxi/cedrus/cedrus_h265.c | 12 ++++++++++++
|
||||
drivers/staging/media/sunxi/cedrus/cedrus_regs.h | 4 ++++
|
||||
drivers/staging/media/sunxi/cedrus/cedrus_video.c | 13 +++++++++++--
|
||||
3 files changed, 27 insertions(+), 2 deletions(-)
|
||||
.../staging/media/sunxi/cedrus/cedrus_h265.c | 12 +++++++++++
|
||||
.../staging/media/sunxi/cedrus/cedrus_regs.h | 4 ++++
|
||||
.../staging/media/sunxi/cedrus/cedrus_video.c | 20 ++++++++++++++-----
|
||||
3 files changed, 31 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||
index 8bbbe69ae51f..04ba7d60ebcd 100644
|
||||
index 97dce6ffbbc5..d866662cd5a5 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||
@@ -453,6 +453,18 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
@@ -520,6 +520,18 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
|
||||
cedrus_write(dev, VE_DEC_H265_DEC_PCM_CTRL, reg);
|
||||
|
||||
@ -30,14 +30,14 @@ index 8bbbe69ae51f..04ba7d60ebcd 100644
|
||||
+ cedrus_write(dev, VE_DEC_H265_10BIT_CONFIGURE, ALIGN(reg, 32));
|
||||
+ }
|
||||
+
|
||||
/* PPS. */
|
||||
|
||||
reg = VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(pps->pps_cr_qp_offset) |
|
||||
VE_DEC_H265_DEC_PPS_CTRL0_PPS_CB_QP_OFFSET(pps->pps_cb_qp_offset) |
|
||||
VE_DEC_H265_DEC_PPS_CTRL0_INIT_QP_MINUS26(pps->init_qp_minus26) |
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
||||
index d1f010ae49ef..dd69031a2779 100644
|
||||
index df1cceef8d93..150eae2d92d2 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
||||
@@ -505,6 +505,10 @@
|
||||
@@ -498,6 +498,10 @@
|
||||
|
||||
#define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80)
|
||||
|
||||
@ -46,25 +46,25 @@ index d1f010ae49ef..dd69031a2779 100644
|
||||
+#define VE_DEC_H265_10BIT_CONFIGURE (VE_ENGINE_DEC_H265 + 0x8c)
|
||||
+
|
||||
#define VE_DEC_H265_LOW_ADDR_PRIMARY_CHROMA(a) \
|
||||
(((a) << 24) & GENMASK(31, 24))
|
||||
SHIFT_AND_MASK_BITS(a, 31, 24)
|
||||
#define VE_DEC_H265_LOW_ADDR_SECONDARY_CHROMA(a) \
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
||||
index d27a9e82ff91..2c2288319c9d 100644
|
||||
index 497b1199d3fe..178ad45b79d8 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
||||
@@ -372,6 +372,7 @@ static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
|
||||
@@ -367,17 +367,27 @@ static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
|
||||
{
|
||||
struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
struct v4l2_pix_format *pix_fmt;
|
||||
+ unsigned int extra_size = 0;
|
||||
u32 directions;
|
||||
|
||||
if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
|
||||
@@ -380,6 +381,14 @@ static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
|
||||
} else {
|
||||
directions = CEDRUS_DECODE_DST;
|
||||
- if (V4L2_TYPE_IS_OUTPUT(vq->type))
|
||||
+ if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
|
||||
pix_fmt = &ctx->src_fmt;
|
||||
- else
|
||||
+ } else {
|
||||
pix_fmt = &ctx->dst_fmt;
|
||||
+
|
||||
|
||||
+ /* The HEVC decoder needs extra size on the output buffer. */
|
||||
+ if (ctx->src_fmt.pixelformat == V4L2_PIX_FMT_HEVC_SLICE) {
|
||||
+ extra_size = DIV_ROUND_UP(pix_fmt->width, 4);
|
||||
@ -72,20 +72,19 @@ index d27a9e82ff91..2c2288319c9d 100644
|
||||
+ extra_size *= ALIGN(pix_fmt->height, 16) * 3;
|
||||
+ extra_size /= 2;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (!cedrus_check_format(pix_fmt->pixelformat, directions,
|
||||
@@ -387,8 +396,8 @@ static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
|
||||
return -EINVAL;
|
||||
|
||||
+ }
|
||||
+
|
||||
if (*nplanes) {
|
||||
- if (sizes[0] < pix_fmt->sizeimage)
|
||||
- return -EINVAL;
|
||||
+ if (sizes[0] < (pix_fmt->sizeimage + extra_size))
|
||||
+ sizes[0] = pix_fmt->sizeimage + extra_size;
|
||||
} else {
|
||||
sizes[0] = pix_fmt->sizeimage;
|
||||
- sizes[0] = pix_fmt->sizeimage;
|
||||
+ sizes[0] = pix_fmt->sizeimage + extra_size;
|
||||
*nplanes = 1;
|
||||
--
|
||||
2.21.0
|
||||
}
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
|
@ -5800,3 +5800,845 @@ index 95c312ae94cf..7646636f2d18 100644
|
||||
--
|
||||
2.23.0
|
||||
|
||||
From de8145452eebe5510bd2b142b31560db548d6abb Mon Sep 17 00:00:00 2001
|
||||
From: Ezequiel Garcia <ezequiel@collabora.com>
|
||||
Date: Thu, 11 Jul 2019 16:26:41 -0400
|
||||
Subject: [PATCH] media: v4l2-ctrl: Move compound control validation
|
||||
|
||||
Rework std_validate moving the compound controls to
|
||||
its own validation function.
|
||||
|
||||
While here, fix the pointer math to account the index parameter.
|
||||
|
||||
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>
|
||||
---
|
||||
drivers/media/v4l2-core/v4l2-ctrls.c | 126 +++++++++++++++------------
|
||||
1 file changed, 69 insertions(+), 57 deletions(-)
|
||||
|
||||
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
index 371537dd8cd3..739418aa9108 100644
|
||||
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
@@ -1629,10 +1629,77 @@ static void std_log(const struct v4l2_ctrl *ctrl)
|
||||
})
|
||||
|
||||
/* Validate a new control */
|
||||
+static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
||||
+ union v4l2_ctrl_ptr ptr)
|
||||
+{
|
||||
+ struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params;
|
||||
+ void *p = ptr.p + idx * ctrl->elem_size;
|
||||
+
|
||||
+ switch ((u32)ctrl->type) {
|
||||
+ case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS:
|
||||
+ p_mpeg2_slice_params = p;
|
||||
+
|
||||
+ switch (p_mpeg2_slice_params->sequence.chroma_format) {
|
||||
+ case 1: /* 4:2:0 */
|
||||
+ case 2: /* 4:2:2 */
|
||||
+ case 3: /* 4:4:4 */
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ switch (p_mpeg2_slice_params->picture.intra_dc_precision) {
|
||||
+ case 0: /* 8 bits */
|
||||
+ case 1: /* 9 bits */
|
||||
+ case 2: /* 10 bits */
|
||||
+ case 3: /* 11 bits */
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ switch (p_mpeg2_slice_params->picture.picture_structure) {
|
||||
+ case 1: /* interlaced top field */
|
||||
+ case 2: /* interlaced bottom field */
|
||||
+ case 3: /* progressive */
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ switch (p_mpeg2_slice_params->picture.picture_coding_type) {
|
||||
+ case V4L2_MPEG2_PICTURE_CODING_TYPE_I:
|
||||
+ case V4L2_MPEG2_PICTURE_CODING_TYPE_P:
|
||||
+ case V4L2_MPEG2_PICTURE_CODING_TYPE_B:
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+
|
||||
+ case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION:
|
||||
+ break;
|
||||
+
|
||||
+ case V4L2_CTRL_TYPE_FWHT_PARAMS:
|
||||
+ break;
|
||||
+
|
||||
+ case V4L2_CTRL_TYPE_H264_SPS:
|
||||
+ case V4L2_CTRL_TYPE_H264_PPS:
|
||||
+ case V4L2_CTRL_TYPE_H264_SCALING_MATRIX:
|
||||
+ case V4L2_CTRL_TYPE_H264_SLICE_PARAMS:
|
||||
+ case V4L2_CTRL_TYPE_H264_DECODE_PARAMS:
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
|
||||
union v4l2_ctrl_ptr ptr)
|
||||
{
|
||||
- struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params;
|
||||
size_t len;
|
||||
u64 offset;
|
||||
s64 val;
|
||||
@@ -1695,63 +1762,8 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
|
||||
return -ERANGE;
|
||||
return 0;
|
||||
|
||||
- case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS:
|
||||
- p_mpeg2_slice_params = ptr.p;
|
||||
-
|
||||
- switch (p_mpeg2_slice_params->sequence.chroma_format) {
|
||||
- case 1: /* 4:2:0 */
|
||||
- case 2: /* 4:2:2 */
|
||||
- case 3: /* 4:4:4 */
|
||||
- break;
|
||||
- default:
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- switch (p_mpeg2_slice_params->picture.intra_dc_precision) {
|
||||
- case 0: /* 8 bits */
|
||||
- case 1: /* 9 bits */
|
||||
- case 2: /* 10 bits */
|
||||
- case 3: /* 11 bits */
|
||||
- break;
|
||||
- default:
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- switch (p_mpeg2_slice_params->picture.picture_structure) {
|
||||
- case 1: /* interlaced top field */
|
||||
- case 2: /* interlaced bottom field */
|
||||
- case 3: /* progressive */
|
||||
- break;
|
||||
- default:
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- switch (p_mpeg2_slice_params->picture.picture_coding_type) {
|
||||
- case V4L2_MPEG2_PICTURE_CODING_TYPE_I:
|
||||
- case V4L2_MPEG2_PICTURE_CODING_TYPE_P:
|
||||
- case V4L2_MPEG2_PICTURE_CODING_TYPE_B:
|
||||
- break;
|
||||
- default:
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-
|
||||
- case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION:
|
||||
- return 0;
|
||||
-
|
||||
- case V4L2_CTRL_TYPE_FWHT_PARAMS:
|
||||
- return 0;
|
||||
-
|
||||
- case V4L2_CTRL_TYPE_H264_SPS:
|
||||
- case V4L2_CTRL_TYPE_H264_PPS:
|
||||
- case V4L2_CTRL_TYPE_H264_SCALING_MATRIX:
|
||||
- case V4L2_CTRL_TYPE_H264_SLICE_PARAMS:
|
||||
- case V4L2_CTRL_TYPE_H264_DECODE_PARAMS:
|
||||
- return 0;
|
||||
-
|
||||
default:
|
||||
- return -EINVAL;
|
||||
+ return std_validate_compound(ctrl, idx, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.23.0
|
||||
|
||||
From a57d6acaf352d91e52271704f45c72e14cd2d98a Mon Sep 17 00:00:00 2001
|
||||
From: Pawel Osciak <posciak@chromium.org>
|
||||
Date: Thu, 11 Jul 2019 16:26:42 -0400
|
||||
Subject: [PATCH] media: uapi: Add VP8 stateless decoder API
|
||||
|
||||
Add the parsed VP8 frame pixel format and controls, to be used
|
||||
with the new stateless decoder API for VP8 to provide parameters
|
||||
for accelerator (aka stateless) codecs.
|
||||
|
||||
Reviewed-by: Tomasz Figa <tfiga@chromium.org>
|
||||
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
|
||||
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
|
||||
Signed-off-by: Pawel Osciak <posciak@chromium.org>
|
||||
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>
|
||||
---
|
||||
Documentation/media/uapi/v4l/biblio.rst | 10 +
|
||||
.../media/uapi/v4l/ext-ctrls-codec.rst | 323 ++++++++++++++++++
|
||||
.../media/uapi/v4l/pixfmt-compressed.rst | 20 ++
|
||||
drivers/media/v4l2-core/v4l2-ctrls.c | 10 +
|
||||
drivers/media/v4l2-core/v4l2-ioctl.c | 1 +
|
||||
include/media/v4l2-ctrls.h | 3 +
|
||||
include/media/vp8-ctrls.h | 110 ++++++
|
||||
7 files changed, 477 insertions(+)
|
||||
create mode 100644 include/media/vp8-ctrls.h
|
||||
|
||||
diff --git a/Documentation/media/uapi/v4l/biblio.rst b/Documentation/media/uapi/v4l/biblio.rst
|
||||
index 8f4eb8823d82..ad2ff258afa8 100644
|
||||
--- a/Documentation/media/uapi/v4l/biblio.rst
|
||||
+++ b/Documentation/media/uapi/v4l/biblio.rst
|
||||
@@ -395,3 +395,13 @@ colimg
|
||||
:title: Color Imaging: Fundamentals and Applications
|
||||
|
||||
:author: Erik Reinhard et al.
|
||||
+
|
||||
+.. _vp8:
|
||||
+
|
||||
+VP8
|
||||
+===
|
||||
+
|
||||
+
|
||||
+:title: RFC 6386: "VP8 Data Format and Decoding Guide"
|
||||
+
|
||||
+:author: J. Bankoski et al.
|
||||
diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
|
||||
index d6ea2ffd65c5..c5f39dd50043 100644
|
||||
--- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
|
||||
+++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
|
||||
@@ -2234,6 +2234,329 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
||||
Quantization parameter for a P frame for FWHT. Valid range: from 1
|
||||
to 31.
|
||||
|
||||
+.. _v4l2-mpeg-vp8:
|
||||
+
|
||||
+``V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER (struct)``
|
||||
+ Specifies the frame parameters for the associated VP8 parsed frame data.
|
||||
+ This includes the necessary parameters for
|
||||
+ configuring a stateless hardware decoding pipeline for VP8.
|
||||
+ The bitstream parameters are defined according to :ref:`vp8`.
|
||||
+
|
||||
+ .. note::
|
||||
+
|
||||
+ This compound control is not yet part of the public kernel API and
|
||||
+ it is expected to change.
|
||||
+
|
||||
+.. c:type:: v4l2_ctrl_vp8_frame_header
|
||||
+
|
||||
+.. cssclass:: longtable
|
||||
+
|
||||
+.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}|
|
||||
+
|
||||
+.. flat-table:: struct v4l2_ctrl_vp8_frame_header
|
||||
+ :header-rows: 0
|
||||
+ :stub-columns: 0
|
||||
+ :widths: 1 1 2
|
||||
+
|
||||
+ * - struct :c:type:`v4l2_vp8_segment_header`
|
||||
+ - ``segment_header``
|
||||
+ - Structure with segment-based adjustments metadata.
|
||||
+ * - struct :c:type:`v4l2_vp8_loopfilter_header`
|
||||
+ - ``loopfilter_header``
|
||||
+ - Structure with loop filter level adjustments metadata.
|
||||
+ * - struct :c:type:`v4l2_vp8_quantization_header`
|
||||
+ - ``quant_header``
|
||||
+ - Structure with VP8 dequantization indices metadata.
|
||||
+ * - struct :c:type:`v4l2_vp8_entropy_header`
|
||||
+ - ``entropy_header``
|
||||
+ - Structure with VP8 entropy coder probabilities metadata.
|
||||
+ * - struct :c:type:`v4l2_vp8_entropy_coder_state`
|
||||
+ - ``coder_state``
|
||||
+ - Structure with VP8 entropy coder state.
|
||||
+ * - __u16
|
||||
+ - ``width``
|
||||
+ - The width of the frame. Must be set for all frames.
|
||||
+ * - __u16
|
||||
+ - ``height``
|
||||
+ - The height of the frame. Must be set for all frames.
|
||||
+ * - __u8
|
||||
+ - ``horizontal_scale``
|
||||
+ - Horizontal scaling factor.
|
||||
+ * - __u8
|
||||
+ - ``vertical_scaling factor``
|
||||
+ - Vertical scale.
|
||||
+ * - __u8
|
||||
+ - ``version``
|
||||
+ - Bitstream version.
|
||||
+ * - __u8
|
||||
+ - ``prob_skip_false``
|
||||
+ - Indicates the probability that the macroblock is not skipped.
|
||||
+ * - __u8
|
||||
+ - ``prob_intra``
|
||||
+ - Indicates the probability that a macroblock is intra-predicted.
|
||||
+ * - __u8
|
||||
+ - ``prob_last``
|
||||
+ - Indicates the probability that the last reference frame is used
|
||||
+ for inter-prediction
|
||||
+ * - __u8
|
||||
+ - ``prob_gf``
|
||||
+ - Indicates the probability that the golden reference frame is used
|
||||
+ for inter-prediction
|
||||
+ * - __u8
|
||||
+ - ``num_dct_parts``
|
||||
+ - Number of DCT coefficients partitions. Must be one of: 1, 2, 4, or 8.
|
||||
+ * - __u32
|
||||
+ - ``first_part_size``
|
||||
+ - Size of the first partition, i.e. the control partition.
|
||||
+ * - __u32
|
||||
+ - ``first_part_header_bits``
|
||||
+ - Size in bits of the first partition header portion.
|
||||
+ * - __u32
|
||||
+ - ``dct_part_sizes[8]``
|
||||
+ - DCT coefficients sizes.
|
||||
+ * - __u64
|
||||
+ - ``last_frame_ts``
|
||||
+ - Timestamp for the V4L2 capture buffer to use as last reference frame, used
|
||||
+ with inter-coded frames. The timestamp refers to the ``timestamp`` field in
|
||||
+ struct :c:type:`v4l2_buffer`. Use the :c:func:`v4l2_timeval_to_ns()`
|
||||
+ function to convert the struct :c:type:`timeval` in struct
|
||||
+ :c:type:`v4l2_buffer` to a __u64.
|
||||
+ * - __u64
|
||||
+ - ``golden_frame_ts``
|
||||
+ - Timestamp for the V4L2 capture buffer to use as last reference frame, used
|
||||
+ with inter-coded frames. The timestamp refers to the ``timestamp`` field in
|
||||
+ struct :c:type:`v4l2_buffer`. Use the :c:func:`v4l2_timeval_to_ns()`
|
||||
+ function to convert the struct :c:type:`timeval` in struct
|
||||
+ :c:type:`v4l2_buffer` to a __u64.
|
||||
+ * - __u64
|
||||
+ - ``alt_frame_ts``
|
||||
+ - Timestamp for the V4L2 capture buffer to use as alternate reference frame, used
|
||||
+ with inter-coded frames. The timestamp refers to the ``timestamp`` field in
|
||||
+ struct :c:type:`v4l2_buffer`. Use the :c:func:`v4l2_timeval_to_ns()`
|
||||
+ function to convert the struct :c:type:`timeval` in struct
|
||||
+ :c:type:`v4l2_buffer` to a __u64.
|
||||
+ * - __u64
|
||||
+ - ``flags``
|
||||
+ - See :ref:`Frame Header Flags <vp8_frame_header_flags>`
|
||||
+
|
||||
+.. _vp8_frame_header_flags:
|
||||
+
|
||||
+``Frame Header Flags``
|
||||
+
|
||||
+.. cssclass:: longtable
|
||||
+
|
||||
+.. flat-table::
|
||||
+ :header-rows: 0
|
||||
+ :stub-columns: 0
|
||||
+ :widths: 1 1 2
|
||||
+
|
||||
+ * - ``V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME``
|
||||
+ - 0x01
|
||||
+ - Indicates if the frame is a key frame.
|
||||
+ * - ``V4L2_VP8_FRAME_HEADER_FLAG_EXPERIMENTAL``
|
||||
+ - 0x02
|
||||
+ - Experimental bitstream.
|
||||
+ * - ``V4L2_VP8_FRAME_HEADER_FLAG_SHOW_FRAME``
|
||||
+ - 0x04
|
||||
+ - Show frame flag, indicates if the frame is for display.
|
||||
+ * - ``V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF``
|
||||
+ - 0x08
|
||||
+ - Enable/disable skipping of macroblocks with no non-zero coefficients.
|
||||
+ * - ``V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN``
|
||||
+ - 0x10
|
||||
+ - Sign of motion vectors when the golden frame is referenced.
|
||||
+ * - ``V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT``
|
||||
+ - 0x20
|
||||
+ - Sign of motion vectors when the alt frame is referenced.
|
||||
+
|
||||
+.. c:type:: v4l2_vp8_entropy_coder_state
|
||||
+
|
||||
+.. cssclass:: longtable
|
||||
+
|
||||
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
||||
+
|
||||
+.. flat-table:: struct v4l2_vp8_entropy_coder_state
|
||||
+ :header-rows: 0
|
||||
+ :stub-columns: 0
|
||||
+ :widths: 1 1 2
|
||||
+
|
||||
+ * - __u8
|
||||
+ - ``range``
|
||||
+ -
|
||||
+ * - __u8
|
||||
+ - ``value``
|
||||
+ -
|
||||
+ * - __u8
|
||||
+ - ``bit_count``
|
||||
+ -
|
||||
+ * - __u8
|
||||
+ - ``padding``
|
||||
+ - Applications and drivers must set this to zero.
|
||||
+
|
||||
+.. c:type:: v4l2_vp8_segment_header
|
||||
+
|
||||
+.. cssclass:: longtable
|
||||
+
|
||||
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
||||
+
|
||||
+.. flat-table:: struct v4l2_vp8_segment_header
|
||||
+ :header-rows: 0
|
||||
+ :stub-columns: 0
|
||||
+ :widths: 1 1 2
|
||||
+
|
||||
+ * - __s8
|
||||
+ - ``quant_update[4]``
|
||||
+ - Signed quantizer value update.
|
||||
+ * - __s8
|
||||
+ - ``lf_update[4]``
|
||||
+ - Signed loop filter level value update.
|
||||
+ * - __u8
|
||||
+ - ``segment_probs[3]``
|
||||
+ - Segment probabilities.
|
||||
+ * - __u8
|
||||
+ - ``padding``
|
||||
+ - Applications and drivers must set this to zero.
|
||||
+ * - __u32
|
||||
+ - ``flags``
|
||||
+ - See :ref:`Segment Header Flags <vp8_segment_header_flags>`
|
||||
+
|
||||
+.. _vp8_segment_header_flags:
|
||||
+
|
||||
+``Segment Header Flags``
|
||||
+
|
||||
+.. cssclass:: longtable
|
||||
+
|
||||
+.. flat-table::
|
||||
+ :header-rows: 0
|
||||
+ :stub-columns: 0
|
||||
+ :widths: 1 1 2
|
||||
+
|
||||
+ * - ``V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED``
|
||||
+ - 0x01
|
||||
+ - Enable/disable segment-based adjustments.
|
||||
+ * - ``V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP``
|
||||
+ - 0x02
|
||||
+ - Indicates if the macroblock segmentation map is updated in this frame.
|
||||
+ * - ``V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_FEATURE_DATA``
|
||||
+ - 0x04
|
||||
+ - Indicates if the segment feature data is updated in this frame.
|
||||
+ * - ``V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE``
|
||||
+ - 0x08
|
||||
+ - If is set, the segment feature data mode is delta-value.
|
||||
+ If cleared, it's absolute-value.
|
||||
+
|
||||
+.. c:type:: v4l2_vp8_loopfilter_header
|
||||
+
|
||||
+.. cssclass:: longtable
|
||||
+
|
||||
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
||||
+
|
||||
+.. flat-table:: struct v4l2_vp8_loopfilter_header
|
||||
+ :header-rows: 0
|
||||
+ :stub-columns: 0
|
||||
+ :widths: 1 1 2
|
||||
+
|
||||
+ * - __s8
|
||||
+ - ``ref_frm_delta[4]``
|
||||
+ - Reference adjustment (signed) delta value.
|
||||
+ * - __s8
|
||||
+ - ``mb_mode_delta[4]``
|
||||
+ - Macroblock prediction mode adjustment (signed) delta value.
|
||||
+ * - __u8
|
||||
+ - ``sharpness_level``
|
||||
+ - Sharpness level
|
||||
+ * - __u8
|
||||
+ - ``level``
|
||||
+ - Filter level
|
||||
+ * - __u16
|
||||
+ - ``padding``
|
||||
+ - Applications and drivers must set this to zero.
|
||||
+ * - __u32
|
||||
+ - ``flags``
|
||||
+ - See :ref:`Loopfilter Header Flags <vp8_loopfilter_header_flags>`
|
||||
+
|
||||
+.. _vp8_loopfilter_header_flags:
|
||||
+
|
||||
+``Loopfilter Header Flags``
|
||||
+
|
||||
+.. cssclass:: longtable
|
||||
+
|
||||
+.. flat-table::
|
||||
+ :header-rows: 0
|
||||
+ :stub-columns: 0
|
||||
+ :widths: 1 1 2
|
||||
+
|
||||
+ * - ``V4L2_VP8_LF_HEADER_ADJ_ENABLE``
|
||||
+ - 0x01
|
||||
+ - Enable/disable macroblock-level loop filter adjustment.
|
||||
+ * - ``V4L2_VP8_LF_HEADER_DELTA_UPDATE``
|
||||
+ - 0x02
|
||||
+ - Indicates if the delta values used in an adjustment are updated.
|
||||
+ * - ``V4L2_VP8_LF_FILTER_TYPE_SIMPLE``
|
||||
+ - 0x04
|
||||
+ - If set, indicates the filter type is simple.
|
||||
+ If cleared, the filter type is normal.
|
||||
+
|
||||
+.. c:type:: v4l2_vp8_quantization_header
|
||||
+
|
||||
+.. cssclass:: longtable
|
||||
+
|
||||
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
||||
+
|
||||
+.. flat-table:: struct v4l2_vp8_quantization_header
|
||||
+ :header-rows: 0
|
||||
+ :stub-columns: 0
|
||||
+ :widths: 1 1 2
|
||||
+
|
||||
+ * - __u8
|
||||
+ - ``y_ac_qi``
|
||||
+ - Luma AC coefficient table index.
|
||||
+ * - __s8
|
||||
+ - ``y_dc_delta``
|
||||
+ - Luma DC delta vaue.
|
||||
+ * - __s8
|
||||
+ - ``y2_dc_delta``
|
||||
+ - Y2 block DC delta value.
|
||||
+ * - __s8
|
||||
+ - ``y2_ac_delta``
|
||||
+ - Y2 block AC delta value.
|
||||
+ * - __s8
|
||||
+ - ``uv_dc_delta``
|
||||
+ - Chroma DC delta value.
|
||||
+ * - __s8
|
||||
+ - ``uv_ac_delta``
|
||||
+ - Chroma AC delta value.
|
||||
+ * - __u16
|
||||
+ - ``padding``
|
||||
+ - Applications and drivers must set this to zero.
|
||||
+
|
||||
+.. c:type:: v4l2_vp8_entropy_header
|
||||
+
|
||||
+.. cssclass:: longtable
|
||||
+
|
||||
+.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}|
|
||||
+
|
||||
+.. flat-table:: struct v4l2_vp8_entropy_header
|
||||
+ :header-rows: 0
|
||||
+ :stub-columns: 0
|
||||
+ :widths: 1 1 2
|
||||
+
|
||||
+ * - __u8
|
||||
+ - ``coeff_probs[4][8][3][11]``
|
||||
+ - Coefficient update probabilities.
|
||||
+ * - __u8
|
||||
+ - ``y_mode_probs[4]``
|
||||
+ - Luma mode update probabilities.
|
||||
+ * - __u8
|
||||
+ - ``uv_mode_probs[3]``
|
||||
+ - Chroma mode update probabilities.
|
||||
+ * - __u8
|
||||
+ - ``mv_probs[2][19]``
|
||||
+ - MV decoding update probabilities.
|
||||
+ * - __u8
|
||||
+ - ``padding[3]``
|
||||
+ - Applications and drivers must set this to zero.
|
||||
+
|
||||
.. raw:: latex
|
||||
|
||||
\normalsize
|
||||
diff --git a/Documentation/media/uapi/v4l/pixfmt-compressed.rst b/Documentation/media/uapi/v4l/pixfmt-compressed.rst
|
||||
index 4b701fc7653e..f52a7b67023d 100644
|
||||
--- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst
|
||||
+++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst
|
||||
@@ -133,6 +133,26 @@ Compressed Formats
|
||||
- ``V4L2_PIX_FMT_VP8``
|
||||
- 'VP80'
|
||||
- VP8 video elementary stream.
|
||||
+ * .. _V4L2-PIX-FMT-VP8-FRAME:
|
||||
+
|
||||
+ - ``V4L2_PIX_FMT_VP8_FRAME``
|
||||
+ - 'VP8F'
|
||||
+ - VP8 parsed frame, as extracted from the container.
|
||||
+ This format is adapted for stateless video decoders that implement a
|
||||
+ VP8 pipeline (using the :ref:`mem2mem` and :ref:`media-request-api`).
|
||||
+ Metadata associated with the frame to decode is required to be passed
|
||||
+ through the ``V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER`` control.
|
||||
+ See the :ref:`associated Codec Control IDs <v4l2-mpeg-vp8>`.
|
||||
+ Exactly one output and one capture buffer must be provided for use with
|
||||
+ this pixel format. The output buffer must contain the appropriate number
|
||||
+ of macroblocks to decode a full corresponding frame to the matching
|
||||
+ capture buffer.
|
||||
+
|
||||
+ .. note::
|
||||
+
|
||||
+ This format is not yet part of the public kernel API and it
|
||||
+ is expected to change.
|
||||
+
|
||||
* .. _V4L2-PIX-FMT-VP9:
|
||||
|
||||
- ``V4L2_PIX_FMT_VP9``
|
||||
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
index 739418aa9108..b2c9f5816c4a 100644
|
||||
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
@@ -885,6 +885,7 @@ const char *v4l2_ctrl_get_name(u32 id)
|
||||
case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP: return "VPX P-Frame QP Value";
|
||||
case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: return "VP8 Profile";
|
||||
case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile";
|
||||
+ case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: return "VP8 Frame Header";
|
||||
|
||||
/* HEVC controls */
|
||||
case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value";
|
||||
@@ -1345,6 +1346,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
|
||||
case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS:
|
||||
*type = V4L2_CTRL_TYPE_H264_DECODE_PARAMS;
|
||||
break;
|
||||
+ case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER:
|
||||
+ *type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER;
|
||||
+ break;
|
||||
default:
|
||||
*type = V4L2_CTRL_TYPE_INTEGER;
|
||||
break;
|
||||
@@ -1690,6 +1694,9 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
||||
case V4L2_CTRL_TYPE_H264_SLICE_PARAMS:
|
||||
case V4L2_CTRL_TYPE_H264_DECODE_PARAMS:
|
||||
break;
|
||||
+
|
||||
+ case V4L2_CTRL_TYPE_VP8_FRAME_HEADER:
|
||||
+ break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -2360,6 +2367,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
|
||||
case V4L2_CTRL_TYPE_H264_DECODE_PARAMS:
|
||||
elem_size = sizeof(struct v4l2_ctrl_h264_decode_params);
|
||||
break;
|
||||
+ case V4L2_CTRL_TYPE_VP8_FRAME_HEADER:
|
||||
+ elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header);
|
||||
+ break;
|
||||
default:
|
||||
if (type < V4L2_CTRL_COMPOUND_TYPES)
|
||||
elem_size = sizeof(s32);
|
||||
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
|
||||
index 20cc23ef730e..80efc581e3f9 100644
|
||||
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
|
||||
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
|
||||
@@ -1348,6 +1348,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
|
||||
case V4L2_PIX_FMT_VC1_ANNEX_G: descr = "VC-1 (SMPTE 412M Annex G)"; break;
|
||||
case V4L2_PIX_FMT_VC1_ANNEX_L: descr = "VC-1 (SMPTE 412M Annex L)"; break;
|
||||
case V4L2_PIX_FMT_VP8: descr = "VP8"; break;
|
||||
+ case V4L2_PIX_FMT_VP8_FRAME: descr = "VP8 Frame"; break;
|
||||
case V4L2_PIX_FMT_VP9: descr = "VP9"; break;
|
||||
case V4L2_PIX_FMT_HEVC: descr = "HEVC"; break; /* aka H.265 */
|
||||
case V4L2_PIX_FMT_FWHT: descr = "FWHT"; break; /* used in vicodec */
|
||||
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
|
||||
index b4433483af23..6e9dc9c44bb1 100644
|
||||
--- a/include/media/v4l2-ctrls.h
|
||||
+++ b/include/media/v4l2-ctrls.h
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <media/mpeg2-ctrls.h>
|
||||
#include <media/fwht-ctrls.h>
|
||||
#include <media/h264-ctrls.h>
|
||||
+#include <media/vp8-ctrls.h>
|
||||
|
||||
/* forward references */
|
||||
struct file;
|
||||
@@ -48,6 +49,7 @@ struct poll_table_struct;
|
||||
* @p_h264_scaling_matrix: Pointer to a struct v4l2_ctrl_h264_scaling_matrix.
|
||||
* @p_h264_slice_params: Pointer to a struct v4l2_ctrl_h264_slice_params.
|
||||
* @p_h264_decode_params: Pointer to a struct v4l2_ctrl_h264_decode_params.
|
||||
+ * @p_vp8_frame_header: Pointer to a VP8 frame header structure.
|
||||
* @p: Pointer to a compound value.
|
||||
*/
|
||||
union v4l2_ctrl_ptr {
|
||||
@@ -65,6 +67,7 @@ union v4l2_ctrl_ptr {
|
||||
struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix;
|
||||
struct v4l2_ctrl_h264_slice_params *p_h264_slice_params;
|
||||
struct v4l2_ctrl_h264_decode_params *p_h264_decode_params;
|
||||
+ struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header;
|
||||
void *p;
|
||||
};
|
||||
|
||||
diff --git a/include/media/vp8-ctrls.h b/include/media/vp8-ctrls.h
|
||||
new file mode 100644
|
||||
index 000000000000..6cc2eeea4c90
|
||||
--- /dev/null
|
||||
+++ b/include/media/vp8-ctrls.h
|
||||
@@ -0,0 +1,110 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0 */
|
||||
+/*
|
||||
+ * These are the VP8 state controls for use with stateless VP8
|
||||
+ * codec drivers.
|
||||
+ *
|
||||
+ * It turns out that these structs are not stable yet and will undergo
|
||||
+ * more changes. So keep them private until they are stable and ready to
|
||||
+ * become part of the official public API.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _VP8_CTRLS_H_
|
||||
+#define _VP8_CTRLS_H_
|
||||
+
|
||||
+#define V4L2_PIX_FMT_VP8_FRAME v4l2_fourcc('V', 'P', '8', 'F')
|
||||
+
|
||||
+#define V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER (V4L2_CID_MPEG_BASE + 2000)
|
||||
+#define V4L2_CTRL_TYPE_VP8_FRAME_HEADER 0x301
|
||||
+
|
||||
+#define V4L2_VP8_SEGMENT_HEADER_FLAG_ENABLED 0x01
|
||||
+#define V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_MAP 0x02
|
||||
+#define V4L2_VP8_SEGMENT_HEADER_FLAG_UPDATE_FEATURE_DATA 0x04
|
||||
+#define V4L2_VP8_SEGMENT_HEADER_FLAG_DELTA_VALUE_MODE 0x08
|
||||
+
|
||||
+struct v4l2_vp8_segment_header {
|
||||
+ __s8 quant_update[4];
|
||||
+ __s8 lf_update[4];
|
||||
+ __u8 segment_probs[3];
|
||||
+ __u8 padding;
|
||||
+ __u32 flags;
|
||||
+};
|
||||
+
|
||||
+#define V4L2_VP8_LF_HEADER_ADJ_ENABLE 0x01
|
||||
+#define V4L2_VP8_LF_HEADER_DELTA_UPDATE 0x02
|
||||
+#define V4L2_VP8_LF_FILTER_TYPE_SIMPLE 0x04
|
||||
+struct v4l2_vp8_loopfilter_header {
|
||||
+ __s8 ref_frm_delta[4];
|
||||
+ __s8 mb_mode_delta[4];
|
||||
+ __u8 sharpness_level;
|
||||
+ __u8 level;
|
||||
+ __u16 padding;
|
||||
+ __u32 flags;
|
||||
+};
|
||||
+
|
||||
+struct v4l2_vp8_quantization_header {
|
||||
+ __u8 y_ac_qi;
|
||||
+ __s8 y_dc_delta;
|
||||
+ __s8 y2_dc_delta;
|
||||
+ __s8 y2_ac_delta;
|
||||
+ __s8 uv_dc_delta;
|
||||
+ __s8 uv_ac_delta;
|
||||
+ __u16 padding;
|
||||
+};
|
||||
+
|
||||
+struct v4l2_vp8_entropy_header {
|
||||
+ __u8 coeff_probs[4][8][3][11];
|
||||
+ __u8 y_mode_probs[4];
|
||||
+ __u8 uv_mode_probs[3];
|
||||
+ __u8 mv_probs[2][19];
|
||||
+ __u8 padding[3];
|
||||
+};
|
||||
+
|
||||
+struct v4l2_vp8_entropy_coder_state {
|
||||
+ __u8 range;
|
||||
+ __u8 value;
|
||||
+ __u8 bit_count;
|
||||
+ __u8 padding;
|
||||
+};
|
||||
+
|
||||
+#define V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME 0x01
|
||||
+#define V4L2_VP8_FRAME_HEADER_FLAG_EXPERIMENTAL 0x02
|
||||
+#define V4L2_VP8_FRAME_HEADER_FLAG_SHOW_FRAME 0x04
|
||||
+#define V4L2_VP8_FRAME_HEADER_FLAG_MB_NO_SKIP_COEFF 0x08
|
||||
+#define V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_GOLDEN 0x10
|
||||
+#define V4L2_VP8_FRAME_HEADER_FLAG_SIGN_BIAS_ALT 0x20
|
||||
+
|
||||
+#define VP8_FRAME_IS_KEY_FRAME(hdr) \
|
||||
+ (!!((hdr)->flags & V4L2_VP8_FRAME_HEADER_FLAG_KEY_FRAME))
|
||||
+
|
||||
+struct v4l2_ctrl_vp8_frame_header {
|
||||
+ struct v4l2_vp8_segment_header segment_header;
|
||||
+ struct v4l2_vp8_loopfilter_header lf_header;
|
||||
+ struct v4l2_vp8_quantization_header quant_header;
|
||||
+ struct v4l2_vp8_entropy_header entropy_header;
|
||||
+ struct v4l2_vp8_entropy_coder_state coder_state;
|
||||
+
|
||||
+ __u16 width;
|
||||
+ __u16 height;
|
||||
+
|
||||
+ __u8 horizontal_scale;
|
||||
+ __u8 vertical_scale;
|
||||
+
|
||||
+ __u8 version;
|
||||
+ __u8 prob_skip_false;
|
||||
+ __u8 prob_intra;
|
||||
+ __u8 prob_last;
|
||||
+ __u8 prob_gf;
|
||||
+ __u8 num_dct_parts;
|
||||
+
|
||||
+ __u32 first_part_size;
|
||||
+ __u32 first_part_header_bits;
|
||||
+ __u32 dct_part_sizes[8];
|
||||
+
|
||||
+ __u64 last_frame_ts;
|
||||
+ __u64 golden_frame_ts;
|
||||
+ __u64 alt_frame_ts;
|
||||
+
|
||||
+ __u64 flags;
|
||||
+};
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
2.23.0
|
||||
|
||||
From 298c62d3856111e6ef41c9c00a233aecf2d19651 Mon Sep 17 00:00:00 2001
|
||||
From: Ezequiel Garcia <ezequiel@collabora.com>
|
||||
Date: Thu, 11 Jul 2019 16:26:43 -0400
|
||||
Subject: [PATCH] media: v4l2-ctrl: Validate VP8 stateless decoder controls
|
||||
|
||||
Only one field needs to be validated: 'num_dct_parts'.
|
||||
This field is used to iterate over the user-provided array
|
||||
'dct_part_sizes'.
|
||||
|
||||
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
|
||||
[hverkuil-cisco@xs4all.nl: s -> (s) in zero_padding macro]
|
||||
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
||||
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
|
||||
---
|
||||
drivers/media/v4l2-core/v4l2-ctrls.c | 21 +++++++++++++++++++++
|
||||
1 file changed, 21 insertions(+)
|
||||
|
||||
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
index b2c9f5816c4a..13236c191796 100644
|
||||
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
@@ -1633,10 +1633,15 @@ static void std_log(const struct v4l2_ctrl *ctrl)
|
||||
})
|
||||
|
||||
/* Validate a new control */
|
||||
+
|
||||
+#define zero_padding(s) \
|
||||
+ memset(&(s).padding, 0, sizeof((s).padding))
|
||||
+
|
||||
static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
||||
union v4l2_ctrl_ptr ptr)
|
||||
{
|
||||
struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params;
|
||||
+ struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header;
|
||||
void *p = ptr.p + idx * ctrl->elem_size;
|
||||
|
||||
switch ((u32)ctrl->type) {
|
||||
@@ -1696,6 +1701,22 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
||||
break;
|
||||
|
||||
case V4L2_CTRL_TYPE_VP8_FRAME_HEADER:
|
||||
+ p_vp8_frame_header = p;
|
||||
+
|
||||
+ switch (p_vp8_frame_header->num_dct_parts) {
|
||||
+ case 1:
|
||||
+ case 2:
|
||||
+ case 4:
|
||||
+ case 8:
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ zero_padding(p_vp8_frame_header->segment_header);
|
||||
+ zero_padding(p_vp8_frame_header->lf_header);
|
||||
+ zero_padding(p_vp8_frame_header->quant_header);
|
||||
+ zero_padding(p_vp8_frame_header->entropy_header);
|
||||
+ zero_padding(p_vp8_frame_header->coder_state);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
--
|
||||
2.23.0
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1407
projects/Allwinner/patches/linux/0005-cedrus-improvements.patch
Normal file
1407
projects/Allwinner/patches/linux/0005-cedrus-improvements.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,76 +0,0 @@
|
||||
From 443ca53cf78c635aa5bebe9f115721e55fe9ca38 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sat, 25 May 2019 12:33:05 +0200
|
||||
Subject: [PATCH] media: cedrus: Fix decoding for some H264 videos
|
||||
|
||||
It seems that for some H264 videos at least one bitstream parsing
|
||||
trigger must be called in order to be decoded correctly. There is no
|
||||
explanation why this helps, but it was observed that two sample videos
|
||||
with this fix are now decoded correctly and there is no regression with
|
||||
others.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../staging/media/sunxi/cedrus/cedrus_h264.c | 22 ++++++++++++++++---
|
||||
1 file changed, 19 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
||||
index a30bb283f69f..fab14de1815a 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
||||
@@ -6,6 +6,7 @@
|
||||
* Copyright (c) 2018 Bootlin
|
||||
*/
|
||||
|
||||
+#include <linux/delay.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <media/videobuf2-dma-contig.h>
|
||||
@@ -289,6 +290,20 @@ static void cedrus_write_pred_weight_table(struct cedrus_ctx *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
+static void cedrus_skip_bits(struct cedrus_dev *dev, int num)
|
||||
+{
|
||||
+ for (; num > 32; num -= 32) {
|
||||
+ cedrus_write(dev, VE_H264_TRIGGER_TYPE, 0x3 | (32 << 8));
|
||||
+ while (cedrus_read(dev, VE_H264_STATUS) & (1 << 8))
|
||||
+ udelay(1);
|
||||
+ }
|
||||
+ if (num > 0) {
|
||||
+ cedrus_write(dev, VE_H264_TRIGGER_TYPE, 0x3 | (num << 8));
|
||||
+ while (cedrus_read(dev, VE_H264_STATUS) & (1 << 8))
|
||||
+ udelay(1);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void cedrus_set_params(struct cedrus_ctx *ctx,
|
||||
struct cedrus_run *run)
|
||||
{
|
||||
@@ -299,12 +314,11 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
||||
struct vb2_buffer *src_buf = &run->src->vb2_buf;
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
dma_addr_t src_buf_addr;
|
||||
- u32 offset = slice->header_bit_size;
|
||||
- u32 len = (slice->size * 8) - offset;
|
||||
+ u32 len = slice->size * 8;
|
||||
u32 reg;
|
||||
|
||||
cedrus_write(dev, VE_H264_VLD_LEN, len);
|
||||
- cedrus_write(dev, VE_H264_VLD_OFFSET, offset);
|
||||
+ cedrus_write(dev, VE_H264_VLD_OFFSET, 0);
|
||||
|
||||
src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
|
||||
cedrus_write(dev, VE_H264_VLD_END,
|
||||
@@ -323,6 +337,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
||||
cedrus_write(dev, VE_H264_TRIGGER_TYPE,
|
||||
VE_H264_TRIGGER_TYPE_INIT_SWDEC);
|
||||
|
||||
+ cedrus_skip_bits(dev, slice->header_bit_size);
|
||||
+
|
||||
if (((pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) &&
|
||||
(slice->slice_type == V4L2_H264_SLICE_TYPE_P ||
|
||||
slice->slice_type == V4L2_H264_SLICE_TYPE_SP)) ||
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,36 +0,0 @@
|
||||
From fce7f7e700176b402b303d2a62813cc0cdd061e0 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sat, 25 May 2019 13:18:50 +0200
|
||||
Subject: [PATCH 2/5] media: cedrus: Fix H264 default reference index count
|
||||
|
||||
Reference index count in VE_H264_PPS should come from PPS control.
|
||||
However, this is not really important, because reference index count is
|
||||
in our case always overridden by that from slice header.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 8 ++------
|
||||
1 file changed, 2 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
||||
index fab14de1815a..d0ee3f90ff46 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
||||
@@ -356,12 +356,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
||||
|
||||
// picture parameters
|
||||
reg = 0;
|
||||
- /*
|
||||
- * FIXME: the kernel headers are allowing the default value to
|
||||
- * be passed, but the libva doesn't give us that.
|
||||
- */
|
||||
- reg |= (slice->num_ref_idx_l0_active_minus1 & 0x1f) << 10;
|
||||
- reg |= (slice->num_ref_idx_l1_active_minus1 & 0x1f) << 5;
|
||||
+ reg |= (pps->num_ref_idx_l0_default_active_minus1 & 0x1f) << 10;
|
||||
+ reg |= (pps->num_ref_idx_l1_default_active_minus1 & 0x1f) << 5;
|
||||
reg |= (pps->weighted_bipred_idc & 0x3) << 2;
|
||||
if (pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE)
|
||||
reg |= VE_H264_PPS_ENTROPY_CODING_MODE;
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,124 +0,0 @@
|
||||
From 9714cf1bc8c5b48f21af3500e34497621b51a4b1 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Thu, 14 Feb 2019 22:50:12 +0100
|
||||
Subject: [PATCH 3/5] media: cedrus: WIP H264 improvements
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
.../staging/media/sunxi/cedrus/cedrus_h264.c | 37 ++++++++++++++-----
|
||||
1 file changed, 27 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
||||
index d0ee3f90ff46..dcb8d3837869 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
||||
@@ -39,7 +39,7 @@ struct cedrus_h264_sram_ref_pic {
|
||||
#define CEDRUS_H264_FRAME_NUM 18
|
||||
|
||||
#define CEDRUS_NEIGHBOR_INFO_BUF_SIZE (16 * SZ_1K)
|
||||
-#define CEDRUS_PIC_INFO_BUF_SIZE (128 * SZ_1K)
|
||||
+#define CEDRUS_PIC_INFO_BUF_SIZE (336 * SZ_1K)
|
||||
|
||||
static void cedrus_h264_write_sram(struct cedrus_dev *dev,
|
||||
enum cedrus_h264_sram_off off,
|
||||
@@ -102,7 +102,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
unsigned long used_dpbs = 0;
|
||||
unsigned int position;
|
||||
- unsigned int output = 0;
|
||||
+ int output = -1;
|
||||
unsigned int i;
|
||||
|
||||
memset(pic_list, 0, sizeof(pic_list));
|
||||
@@ -123,6 +123,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
|
||||
position = cedrus_buf->codec.h264.position;
|
||||
used_dpbs |= BIT(position);
|
||||
|
||||
+ if (run->dst->vb2_buf.timestamp == dpb->reference_ts) {
|
||||
+ output = position;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
|
||||
continue;
|
||||
|
||||
@@ -130,13 +135,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
|
||||
dpb->top_field_order_cnt,
|
||||
dpb->bottom_field_order_cnt,
|
||||
&pic_list[position]);
|
||||
-
|
||||
- output = max(position, output);
|
||||
}
|
||||
|
||||
- position = find_next_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM,
|
||||
- output);
|
||||
- if (position >= CEDRUS_H264_FRAME_NUM)
|
||||
+ if (output >= 0)
|
||||
+ position = output;
|
||||
+ else
|
||||
position = find_first_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM);
|
||||
|
||||
output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf);
|
||||
@@ -162,6 +165,10 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
|
||||
|
||||
#define CEDRUS_MAX_REF_IDX 32
|
||||
|
||||
+#define REF_IDX(v) (v & GENMASK(5, 0))
|
||||
+#define REF_FIELD(v) (v >> 6)
|
||||
+#define REF_FIELD_BOTTOM 2
|
||||
+
|
||||
static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
|
||||
struct cedrus_run *run,
|
||||
const u8 *ref_list, u8 num_ref,
|
||||
@@ -184,7 +191,7 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
|
||||
int buf_idx;
|
||||
u8 dpb_idx;
|
||||
|
||||
- dpb_idx = ref_list[i];
|
||||
+ dpb_idx = REF_IDX(ref_list[i]);
|
||||
dpb = &decode->dpb[dpb_idx];
|
||||
|
||||
if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
|
||||
@@ -199,7 +206,8 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
|
||||
position = cedrus_buf->codec.h264.position;
|
||||
|
||||
sram_array[i] |= position << 1;
|
||||
- if (ref_buf->field == V4L2_FIELD_BOTTOM)
|
||||
+ /* set bottom field flag when reference is to bottom field */
|
||||
+ if (REF_FIELD(ref_list[i]) == REF_FIELD_BOTTOM)
|
||||
sram_array[i] |= BIT(0);
|
||||
}
|
||||
|
||||
@@ -315,6 +323,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
dma_addr_t src_buf_addr;
|
||||
u32 len = slice->size * 8;
|
||||
+ unsigned int pic_width_in_mbs;
|
||||
+ bool mbaff_picture;
|
||||
u32 reg;
|
||||
|
||||
cedrus_write(dev, VE_H264_VLD_LEN, len);
|
||||
@@ -382,12 +392,19 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
||||
reg |= VE_H264_SPS_DIRECT_8X8_INFERENCE;
|
||||
cedrus_write(dev, VE_H264_SPS, reg);
|
||||
|
||||
+ mbaff_picture = !(slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) &&
|
||||
+ (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD);
|
||||
+ pic_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1;
|
||||
+
|
||||
// slice parameters
|
||||
reg = 0;
|
||||
+ reg |= ((slice->first_mb_in_slice % pic_width_in_mbs) & 0xff) << 24;
|
||||
+ reg |= (((slice->first_mb_in_slice / pic_width_in_mbs) * (mbaff_picture ? 2 : 1)) & 0xff) << 16;
|
||||
reg |= decode->nal_ref_idc ? BIT(12) : 0;
|
||||
reg |= (slice->slice_type & 0xf) << 8;
|
||||
reg |= slice->cabac_init_idc & 0x3;
|
||||
- reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC;
|
||||
+ if (decode->num_slices == 1)
|
||||
+ reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC;
|
||||
if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)
|
||||
reg |= VE_H264_SHS_FIELD_PIC;
|
||||
if (slice->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,781 +0,0 @@
|
||||
From c6582c38df2f78dc9d4f8fd920780a82a01e4d8e Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sat, 25 May 2019 13:58:17 +0200
|
||||
Subject: [PATCH 2/3] WIP: HEVC improvements
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
drivers/media/v4l2-core/v4l2-ctrls.c | 8 +
|
||||
drivers/staging/media/sunxi/cedrus/cedrus.c | 6 +
|
||||
drivers/staging/media/sunxi/cedrus/cedrus.h | 11 +-
|
||||
.../staging/media/sunxi/cedrus/cedrus_dec.c | 2 +
|
||||
.../staging/media/sunxi/cedrus/cedrus_h265.c | 348 +++++++++++++-----
|
||||
.../staging/media/sunxi/cedrus/cedrus_regs.h | 3 +
|
||||
.../staging/media/sunxi/cedrus/cedrus_video.c | 12 +-
|
||||
include/media/hevc-ctrls.h | 20 +-
|
||||
8 files changed, 301 insertions(+), 109 deletions(-)
|
||||
|
||||
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
index 1107698b9d06..aed7a4526193 100644
|
||||
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
|
||||
@@ -947,6 +947,7 @@ const char *v4l2_ctrl_get_name(u32 id)
|
||||
case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set";
|
||||
case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set";
|
||||
case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters";
|
||||
+ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: return "HEVC Scaling Matrix";
|
||||
|
||||
/* CAMERA controls */
|
||||
/* Keep the order of the 'case's the same as in v4l2-controls.h! */
|
||||
@@ -1368,6 +1369,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
|
||||
case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS:
|
||||
*type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS;
|
||||
break;
|
||||
+ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX:
|
||||
+ *type = V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX;
|
||||
+ break;
|
||||
default:
|
||||
*type = V4L2_CTRL_TYPE_INTEGER;
|
||||
break;
|
||||
@@ -1747,6 +1751,7 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
|
||||
case V4L2_CTRL_TYPE_HEVC_SPS:
|
||||
case V4L2_CTRL_TYPE_HEVC_PPS:
|
||||
case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS:
|
||||
+ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
@@ -2356,6 +2361,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
|
||||
case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS:
|
||||
elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params);
|
||||
break;
|
||||
+ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX:
|
||||
+ elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix);
|
||||
+ break;
|
||||
default:
|
||||
if (type < V4L2_CTRL_COMPOUND_TYPES)
|
||||
elem_size = sizeof(s32);
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
||||
index 70642834f351..01860f247aa6 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
||||
@@ -88,6 +88,13 @@ static const struct cedrus_control cedrus_controls[] = {
|
||||
.codec = CEDRUS_CODEC_H265,
|
||||
.required = true,
|
||||
},
|
||||
+ {
|
||||
+ .cfg = {
|
||||
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX,
|
||||
+ },
|
||||
+ .codec = CEDRUS_CODEC_H265,
|
||||
+ .required = true,
|
||||
+ },
|
||||
};
|
||||
|
||||
#define CEDRUS_CONTROLS_COUNT ARRAY_SIZE(cedrus_controls)
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
||||
index f19be772d78b..b518c5613fdf 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
||||
@@ -74,6 +74,7 @@ struct cedrus_h265_run {
|
||||
const struct v4l2_ctrl_hevc_sps *sps;
|
||||
const struct v4l2_ctrl_hevc_pps *pps;
|
||||
const struct v4l2_ctrl_hevc_slice_params *slice_params;
|
||||
+ const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix;
|
||||
};
|
||||
|
||||
struct cedrus_run {
|
||||
@@ -90,6 +91,10 @@ struct cedrus_run {
|
||||
struct cedrus_buffer {
|
||||
struct v4l2_m2m_buffer m2m_buf;
|
||||
|
||||
+ void *mv_col_buf;
|
||||
+ dma_addr_t mv_col_buf_dma;
|
||||
+ ssize_t mv_col_buf_size;
|
||||
+
|
||||
union {
|
||||
struct {
|
||||
unsigned int position;
|
||||
@@ -123,12 +128,10 @@ struct cedrus_ctx {
|
||||
dma_addr_t neighbor_info_buf_dma;
|
||||
} h264;
|
||||
struct {
|
||||
- void *mv_col_buf;
|
||||
- dma_addr_t mv_col_buf_addr;
|
||||
- ssize_t mv_col_buf_size;
|
||||
- ssize_t mv_col_buf_unit_size;
|
||||
void *neighbor_info_buf;
|
||||
dma_addr_t neighbor_info_buf_addr;
|
||||
+ void *entry_points_buf;
|
||||
+ dma_addr_t entry_points_buf_addr;
|
||||
} h265;
|
||||
} codec;
|
||||
};
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
|
||||
index c6d0ef66cdd0..104adb08492c 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
|
||||
@@ -66,6 +66,8 @@ void cedrus_device_run(void *priv)
|
||||
V4L2_CID_MPEG_VIDEO_HEVC_PPS);
|
||||
run.h265.slice_params = cedrus_find_control_data(ctx,
|
||||
V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS);
|
||||
+ run.h265.scaling_matrix = cedrus_find_control_data(ctx,
|
||||
+ V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX);
|
||||
break;
|
||||
|
||||
default:
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||
index fd4d86b02156..82d29c59b787 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||
@@ -77,24 +77,32 @@ static void cedrus_h265_sram_write_offset(struct cedrus_dev *dev, u32 offset)
|
||||
cedrus_write(dev, VE_DEC_H265_SRAM_OFFSET, offset);
|
||||
}
|
||||
|
||||
-static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data,
|
||||
+static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, const void *data,
|
||||
unsigned int size)
|
||||
{
|
||||
- u32 *word = data;
|
||||
+ size_t count = DIV_ROUND_UP(size, 4);
|
||||
+ const u32 *word = data;
|
||||
|
||||
- while (size >= sizeof(u32)) {
|
||||
+ while (count--)
|
||||
cedrus_write(dev, VE_DEC_H265_SRAM_DATA, *word++);
|
||||
- size -= sizeof(u32);
|
||||
- }
|
||||
}
|
||||
|
||||
static inline dma_addr_t
|
||||
cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx,
|
||||
- unsigned int index, unsigned int field)
|
||||
+ unsigned int index)
|
||||
{
|
||||
- return ctx->codec.h265.mv_col_buf_addr + index *
|
||||
- ctx->codec.h265.mv_col_buf_unit_size +
|
||||
- field * ctx->codec.h265.mv_col_buf_unit_size / 2;
|
||||
+ struct cedrus_buffer *cedrus_buf = NULL;
|
||||
+ struct vb2_buffer *buf = NULL;
|
||||
+ struct vb2_queue *vq;
|
||||
+
|
||||
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
||||
+ if (vq)
|
||||
+ buf = vb2_get_buffer(vq, index);
|
||||
+
|
||||
+ if (buf)
|
||||
+ cedrus_buf = vb2_to_cedrus_buffer(buf);
|
||||
+
|
||||
+ return cedrus_buf ? cedrus_buf->mv_col_buf_dma : 0;
|
||||
}
|
||||
|
||||
static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
|
||||
@@ -107,9 +108,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
|
||||
dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 0);
|
||||
dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 1);
|
||||
dma_addr_t mv_col_buf_addr[2] = {
|
||||
- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, 0),
|
||||
- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index,
|
||||
- field_pic ? 1 : 0)
|
||||
+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index),
|
||||
+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index)
|
||||
};
|
||||
u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO +
|
||||
VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index;
|
||||
@@ -158,28 +158,24 @@ static void cedrus_h265_ref_pic_list_write(struct cedrus_dev *dev,
|
||||
u8 num_ref_idx_active,
|
||||
u32 sram_offset)
|
||||
{
|
||||
+ u8 sram_array[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
|
||||
unsigned int i;
|
||||
- u32 word = 0;
|
||||
+
|
||||
+ memset(sram_array, 0, sizeof(sram_array));
|
||||
+ num_ref_idx_active = min(num_ref_idx_active,
|
||||
+ (u8)V4L2_HEVC_DPB_ENTRIES_NUM_MAX);
|
||||
|
||||
cedrus_h265_sram_write_offset(dev, sram_offset);
|
||||
|
||||
for (i = 0; i < num_ref_idx_active; i++) {
|
||||
- unsigned int shift = (i % 4) * 8;
|
||||
unsigned int index = list[i];
|
||||
- u8 value = list[i];
|
||||
|
||||
+ sram_array[i] = index;
|
||||
if (dpb[index].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR)
|
||||
- value |= VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF;
|
||||
-
|
||||
- /* Each SRAM word gathers up to 4 references. */
|
||||
- word |= value << shift;
|
||||
-
|
||||
- /* Write the word to SRAM and clear it for the next batch. */
|
||||
- if ((i % 4) == 3 || i == (num_ref_idx_active - 1)) {
|
||||
- cedrus_h265_sram_write_data(dev, &word, sizeof(word));
|
||||
- word = 0;
|
||||
- }
|
||||
+ sram_array[i] |= VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF;
|
||||
}
|
||||
+
|
||||
+ cedrus_h265_sram_write_data(dev, &sram_array, num_ref_idx_active);
|
||||
}
|
||||
|
||||
static void cedrus_h265_pred_weight_write(struct cedrus_dev *dev,
|
||||
@@ -220,6 +216,131 @@ static void cedrus_h265_pred_weight_write(struct cedrus_dev *dev,
|
||||
}
|
||||
}
|
||||
|
||||
+static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx,
|
||||
+ struct cedrus_run *run)
|
||||
+{
|
||||
+ const struct v4l2_ctrl_hevc_scaling_matrix *scaling;
|
||||
+ struct cedrus_dev *dev = ctx->dev;
|
||||
+ u32 i, j, k, val;
|
||||
+
|
||||
+ scaling = run->h265.scaling_matrix;
|
||||
+
|
||||
+ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF0,
|
||||
+ (scaling->scaling_list_dc_coef_32x32[1] << 24) |
|
||||
+ (scaling->scaling_list_dc_coef_32x32[0] << 16) |
|
||||
+ (scaling->scaling_list_dc_coef_16x16[1] << 8) |
|
||||
+ (scaling->scaling_list_dc_coef_16x16[0] << 0));
|
||||
+
|
||||
+ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF1,
|
||||
+ (scaling->scaling_list_dc_coef_16x16[5] << 24) |
|
||||
+ (scaling->scaling_list_dc_coef_16x16[4] << 16) |
|
||||
+ (scaling->scaling_list_dc_coef_16x16[3] << 8) |
|
||||
+ (scaling->scaling_list_dc_coef_16x16[2] << 0));
|
||||
+
|
||||
+ cedrus_h265_sram_write_offset(dev, VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS);
|
||||
+
|
||||
+ for (i = 0; i < 6; i++)
|
||||
+ for (j = 0; j < 8; j++)
|
||||
+ for (k = 0; k < 8; k += 4) {
|
||||
+ val = ((u32)scaling->scaling_list_8x8[i][j + (k + 3) * 8] << 24) |
|
||||
+ ((u32)scaling->scaling_list_8x8[i][j + (k + 2) * 8] << 16) |
|
||||
+ ((u32)scaling->scaling_list_8x8[i][j + (k + 1) * 8] << 8) |
|
||||
+ scaling->scaling_list_8x8[i][j + k * 8];
|
||||
+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < 2; i++)
|
||||
+ for (j = 0; j < 8; j++)
|
||||
+ for (k = 0; k < 8; k += 4) {
|
||||
+ val = ((u32)scaling->scaling_list_32x32[i][j + (k + 3) * 8] << 24) |
|
||||
+ ((u32)scaling->scaling_list_32x32[i][j + (k + 2) * 8] << 16) |
|
||||
+ ((u32)scaling->scaling_list_32x32[i][j + (k + 1) * 8] << 8) |
|
||||
+ scaling->scaling_list_32x32[i][j + k * 8];
|
||||
+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < 6; i++)
|
||||
+ for (j = 0; j < 8; j++)
|
||||
+ for (k = 0; k < 8; k += 4) {
|
||||
+ val = ((u32)scaling->scaling_list_16x16[i][j + (k + 3) * 8] << 24) |
|
||||
+ ((u32)scaling->scaling_list_16x16[i][j + (k + 2) * 8] << 16) |
|
||||
+ ((u32)scaling->scaling_list_16x16[i][j + (k + 1) * 8] << 8) |
|
||||
+ scaling->scaling_list_16x16[i][j + k * 8];
|
||||
+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < 6; i++)
|
||||
+ for (j = 0; j < 4; j++) {
|
||||
+ val = ((u32)scaling->scaling_list_4x4[i][j + 12] << 24) |
|
||||
+ ((u32)scaling->scaling_list_4x4[i][j + 8] << 16) |
|
||||
+ ((u32)scaling->scaling_list_4x4[i][j + 4] << 8) |
|
||||
+ scaling->scaling_list_4x4[i][j];
|
||||
+ cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void write_entry_point_list(struct cedrus_ctx *ctx,
|
||||
+ struct cedrus_run *run)
|
||||
+{
|
||||
+ const struct v4l2_ctrl_hevc_slice_params *slice_params;
|
||||
+ unsigned int ctb_size_luma, width_in_ctb_luma;
|
||||
+ unsigned int log2_max_luma_coding_block_size;
|
||||
+ const struct v4l2_ctrl_hevc_pps *pps;
|
||||
+ const struct v4l2_ctrl_hevc_sps *sps;
|
||||
+ struct cedrus_dev *dev = ctx->dev;
|
||||
+ uint32_t *entry_points;
|
||||
+ int i, x, tx, y, ty;
|
||||
+
|
||||
+ pps = run->h265.pps;
|
||||
+ sps = run->h265.sps;
|
||||
+ slice_params = run->h265.slice_params;
|
||||
+
|
||||
+ log2_max_luma_coding_block_size =
|
||||
+ sps->log2_min_luma_coding_block_size_minus3 + 3 +
|
||||
+ sps->log2_diff_max_min_luma_coding_block_size;
|
||||
+ ctb_size_luma = 1 << log2_max_luma_coding_block_size;
|
||||
+ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
|
||||
+
|
||||
+ for (x = 0, tx = 0; tx < pps->num_tile_columns_minus1 + 1; tx++) {
|
||||
+ if (x + pps->column_width_minus1[tx] + 1 > (slice_params->slice_segment_addr % width_in_ctb_luma))
|
||||
+ break;
|
||||
+
|
||||
+ x += pps->column_width_minus1[tx] + 1;
|
||||
+ }
|
||||
+
|
||||
+ for (y = 0, ty = 0; ty < pps->num_tile_rows_minus1 + 1; ty++) {
|
||||
+ if (y + pps->row_height_minus1[ty] + 1 > (slice_params->slice_segment_addr / width_in_ctb_luma))
|
||||
+ break;
|
||||
+
|
||||
+ y += pps->row_height_minus1[ty] + 1;
|
||||
+ }
|
||||
+
|
||||
+ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, (y << 16) | (x << 0));
|
||||
+ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB,
|
||||
+ ((y + pps->row_height_minus1[ty]) << 16) |
|
||||
+ ((x + pps->column_width_minus1[tx]) << 0));
|
||||
+
|
||||
+ entry_points = ctx->codec.h265.entry_points_buf;
|
||||
+ if (pps->entropy_coding_sync_enabled_flag) {
|
||||
+ for (i = 0; i < slice_params->num_entry_point_offsets; i++)
|
||||
+ entry_points[i] = slice_params->entry_point_offset_minus1[i] + 1;
|
||||
+ } else {
|
||||
+ for (i = 0; i < slice_params->num_entry_point_offsets; i++) {
|
||||
+ if (tx + 1 >= pps->num_tile_columns_minus1 + 1) {
|
||||
+ x = tx = 0;
|
||||
+ y += pps->row_height_minus1[ty++] + 1;
|
||||
+ } else {
|
||||
+ x += pps->column_width_minus1[tx++] + 1;
|
||||
+ }
|
||||
+
|
||||
+ entry_points[i * 4 + 0] = slice_params->entry_point_offset_minus1[i] + 1;
|
||||
+ entry_points[i * 4 + 1] = 0x0;
|
||||
+ entry_points[i * 4 + 2] = (y << 16) | (x << 0);
|
||||
+ entry_points[i * 4 + 3] = ((y + pps->row_height_minus1[ty]) << 16) | ((x + pps->column_width_minus1[tx]) << 0);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
struct cedrus_run *run)
|
||||
{
|
||||
@@ -228,6 +349,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
const struct v4l2_ctrl_hevc_pps *pps;
|
||||
const struct v4l2_ctrl_hevc_slice_params *slice_params;
|
||||
const struct v4l2_hevc_pred_weight_table *pred_weight_table;
|
||||
+ struct cedrus_buffer *cedrus_buf;
|
||||
dma_addr_t src_buf_addr;
|
||||
dma_addr_t src_buf_end_addr;
|
||||
u32 chroma_log2_weight_denom;
|
||||
@@ -240,43 +362,10 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
slice_params = run->h265.slice_params;
|
||||
pred_weight_table = &slice_params->pred_weight_table;
|
||||
|
||||
- /* MV column buffer size and allocation. */
|
||||
- if (!ctx->codec.h265.mv_col_buf_size) {
|
||||
- unsigned int num_buffers =
|
||||
- run->dst->vb2_buf.vb2_queue->num_buffers;
|
||||
- unsigned int log2_max_luma_coding_block_size =
|
||||
- sps->log2_min_luma_coding_block_size_minus3 + 3 +
|
||||
- sps->log2_diff_max_min_luma_coding_block_size;
|
||||
- unsigned int ctb_size_luma =
|
||||
- 1 << log2_max_luma_coding_block_size;
|
||||
-
|
||||
- /*
|
||||
- * Each CTB requires a MV col buffer with a specific unit size.
|
||||
- * Since the address is given with missing lsb bits, 1 KiB is
|
||||
- * added to each buffer to ensure proper alignment.
|
||||
- */
|
||||
- ctx->codec.h265.mv_col_buf_unit_size =
|
||||
- DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) *
|
||||
- DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) *
|
||||
- CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K;
|
||||
-
|
||||
- ctx->codec.h265.mv_col_buf_size = num_buffers *
|
||||
- ctx->codec.h265.mv_col_buf_unit_size;
|
||||
-
|
||||
- ctx->codec.h265.mv_col_buf =
|
||||
- dma_alloc_coherent(dev->dev,
|
||||
- ctx->codec.h265.mv_col_buf_size,
|
||||
- &ctx->codec.h265.mv_col_buf_addr,
|
||||
- GFP_KERNEL);
|
||||
- if (!ctx->codec.h265.mv_col_buf) {
|
||||
- ctx->codec.h265.mv_col_buf_size = 0;
|
||||
- // TODO: Abort the process here.
|
||||
- return;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
/* Activate H265 engine. */
|
||||
cedrus_engine_enable(dev, CEDRUS_CODEC_H265);
|
||||
+ if (sps->pic_width_in_luma_samples > 2048)
|
||||
+ cedrus_write(dev, VE_MODE, cedrus_read(dev, VE_MODE) | BIT(21));
|
||||
|
||||
/* Source offset and length in bits. */
|
||||
|
||||
@@ -300,18 +389,35 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
src_buf_end_addr = src_buf_addr +
|
||||
DIV_ROUND_UP(slice_params->bit_size, 8);
|
||||
|
||||
- reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr);
|
||||
+ reg = VE_DEC_H265_BITS_END_ADDR_BASE(ALIGN(src_buf_end_addr, 1024) - 1);
|
||||
cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg);
|
||||
|
||||
- /* Coding tree block address: start at the beginning. */
|
||||
- reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0);
|
||||
- cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg);
|
||||
-
|
||||
cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
|
||||
cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
|
||||
|
||||
+ if (pps->tiles_enabled_flag || pps->entropy_coding_sync_enabled_flag)
|
||||
+ write_entry_point_list(ctx, run);
|
||||
+
|
||||
+ /* Coding tree block address */
|
||||
+ reg = 0;
|
||||
+ if (!slice_params->first_slice_segment_in_pic_flag) {
|
||||
+ unsigned int ctb_size_luma, width_in_ctb_luma;
|
||||
+ unsigned int log2_max_luma_coding_block_size;
|
||||
+
|
||||
+ log2_max_luma_coding_block_size =
|
||||
+ sps->log2_min_luma_coding_block_size_minus3 + 3 +
|
||||
+ sps->log2_diff_max_min_luma_coding_block_size;
|
||||
+ ctb_size_luma = 1 << log2_max_luma_coding_block_size;
|
||||
+ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
|
||||
+
|
||||
+ reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % width_in_ctb_luma);
|
||||
+ reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / width_in_ctb_luma);
|
||||
+ }
|
||||
+ cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg);
|
||||
+
|
||||
/* Clear the number of correctly-decoded coding tree blocks. */
|
||||
- cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
|
||||
+ if (slice_params->first_slice_segment_in_pic_flag)
|
||||
+ cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
|
||||
|
||||
/* Initialize bitstream access. */
|
||||
cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC);
|
||||
@@ -334,6 +440,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_luma_coding_block_size) |
|
||||
VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_luma_coding_block_size_minus3) |
|
||||
VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(sps->bit_depth_chroma_minus8) |
|
||||
+ VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_LUMA_MINUS8(sps->bit_depth_luma_minus8) |
|
||||
VE_DEC_H265_DEC_SPS_HDR_SEPARATE_COLOUR_PLANE_FLAG(sps->separate_colour_plane_flag) |
|
||||
VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(sps->chroma_format_idc);
|
||||
|
||||
@@ -363,7 +470,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
VE_DEC_H265_DEC_PPS_CTRL1_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG(pps->pps_loop_filter_across_slices_enabled_flag) |
|
||||
VE_DEC_H265_DEC_PPS_CTRL1_LOOP_FILTER_ACROSS_TILES_ENABLED_FLAG(pps->loop_filter_across_tiles_enabled_flag) |
|
||||
VE_DEC_H265_DEC_PPS_CTRL1_ENTROPY_CODING_SYNC_ENABLED_FLAG(pps->entropy_coding_sync_enabled_flag) |
|
||||
- VE_DEC_H265_DEC_PPS_CTRL1_TILES_ENABLED_FLAG(0) |
|
||||
+ VE_DEC_H265_DEC_PPS_CTRL1_TILES_ENABLED_FLAG(pps->tiles_enabled_flag) |
|
||||
VE_DEC_H265_DEC_PPS_CTRL1_TRANSQUANT_BYPASS_ENABLE_FLAG(pps->transquant_bypass_enabled_flag) |
|
||||
VE_DEC_H265_DEC_PPS_CTRL1_WEIGHTED_BIPRED_FLAG(pps->weighted_bipred_flag) |
|
||||
VE_DEC_H265_DEC_PPS_CTRL1_WEIGHTED_PRED_FLAG(pps->weighted_pred_flag);
|
||||
@@ -384,7 +491,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLOUR_PLANE_ID(slice_params->colour_plane_id) |
|
||||
VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TYPE(slice_params->slice_type) |
|
||||
VE_DEC_H265_DEC_SLICE_HDR_INFO0_DEPENDENT_SLICE_SEGMENT_FLAG(pps->dependent_slice_segment_flag) |
|
||||
- VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIRST_SLICE_SEGMENT_IN_PIC_FLAG(1);
|
||||
+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIRST_SLICE_SEGMENT_IN_PIC_FLAG(slice_params->first_slice_segment_in_pic_flag);
|
||||
|
||||
cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg);
|
||||
|
||||
@@ -401,34 +508,68 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
|
||||
chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom +
|
||||
pred_weight_table->delta_chroma_log2_weight_denom;
|
||||
- reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(0) |
|
||||
+ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(slice_params->num_entry_point_offsets) |
|
||||
VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) |
|
||||
VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom);
|
||||
|
||||
cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg);
|
||||
|
||||
+ cedrus_write(dev, VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR, ctx->codec.h265.entry_points_buf_addr >> 8);
|
||||
+
|
||||
/* Decoded picture size. */
|
||||
|
||||
- reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) |
|
||||
- VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(ctx->src_fmt.height);
|
||||
+ reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(sps->pic_width_in_luma_samples) |
|
||||
+ VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(sps->pic_height_in_luma_samples);
|
||||
|
||||
cedrus_write(dev, VE_DEC_H265_DEC_PIC_SIZE, reg);
|
||||
|
||||
- /* Scaling list. */
|
||||
+ /* Scaling list */
|
||||
|
||||
- reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT;
|
||||
+ if (sps->scaling_list_enabled_flag) {
|
||||
+ cedrus_h265_write_scaling_list(ctx, run);
|
||||
+ reg = VE_DEC_H265_SCALING_LIST_CTRL0_ENABLED_FLAG(1);
|
||||
+ } else {
|
||||
+ reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT;
|
||||
+ }
|
||||
cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg);
|
||||
|
||||
/* Neightbor information address. */
|
||||
reg = VE_DEC_H265_NEIGHBOR_INFO_ADDR_BASE(ctx->codec.h265.neighbor_info_buf_addr);
|
||||
cedrus_write(dev, VE_DEC_H265_NEIGHBOR_INFO_ADDR, reg);
|
||||
|
||||
+ cedrus_write(dev, VE_DEC_H265_LOW_ADDR, 0);
|
||||
+
|
||||
/* Write decoded picture buffer in pic list. */
|
||||
cedrus_h265_frame_info_write_dpb(ctx, run->dst->vb2_buf.index, slice_params->dpb,
|
||||
slice_params->num_active_dpb_entries);
|
||||
|
||||
/* Output frame. */
|
||||
|
||||
+ cedrus_buf = vb2_to_cedrus_buffer(ctx->fh.m2m_ctx->cap_q_ctx.q.bufs[run->dst->vb2_buf.index]);
|
||||
+ if (!cedrus_buf->mv_col_buf_size) {
|
||||
+ unsigned int ctb_size_luma, width_in_ctb_luma;
|
||||
+ unsigned int log2_max_luma_coding_block_size;
|
||||
+
|
||||
+ log2_max_luma_coding_block_size =
|
||||
+ sps->log2_min_luma_coding_block_size_minus3 + 3 +
|
||||
+ sps->log2_diff_max_min_luma_coding_block_size;
|
||||
+ ctb_size_luma = 1 << log2_max_luma_coding_block_size;
|
||||
+ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
|
||||
+
|
||||
+ cedrus_buf->mv_col_buf_size = ALIGN(width_in_ctb_luma *
|
||||
+ DIV_ROUND_UP(sps->pic_height_in_luma_samples, ctb_size_luma) *
|
||||
+ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE, 1024);
|
||||
+
|
||||
+ cedrus_buf->mv_col_buf =
|
||||
+ dma_alloc_coherent(dev->dev,
|
||||
+ cedrus_buf->mv_col_buf_size,
|
||||
+ &cedrus_buf->mv_col_buf_dma,
|
||||
+ GFP_KERNEL);
|
||||
+
|
||||
+ if (!cedrus_buf->mv_col_buf)
|
||||
+ cedrus_buf->mv_col_buf_size = 0;
|
||||
+ }
|
||||
+
|
||||
output_pic_list_index = V4L2_HEVC_DPB_ENTRIES_NUM_MAX;
|
||||
pic_order_cnt[0] = slice_params->slice_pic_order_cnt;
|
||||
pic_order_cnt[1] = slice_params->slice_pic_order_cnt;
|
||||
@@ -444,36 +585,36 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_I) {
|
||||
cedrus_h265_ref_pic_list_write(dev, slice_params->dpb,
|
||||
slice_params->ref_idx_l0,
|
||||
- slice_params->num_ref_idx_l0_active_minus1 + 1,
|
||||
- VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0);
|
||||
+ slice_params->num_ref_idx_l0_active_minus1 + 1,
|
||||
+ VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0);
|
||||
|
||||
if (pps->weighted_pred_flag || pps->weighted_bipred_flag)
|
||||
cedrus_h265_pred_weight_write(dev,
|
||||
- pred_weight_table->delta_luma_weight_l0,
|
||||
- pred_weight_table->luma_offset_l0,
|
||||
- pred_weight_table->delta_chroma_weight_l0,
|
||||
- pred_weight_table->chroma_offset_l0,
|
||||
- slice_params->num_ref_idx_l0_active_minus1 + 1,
|
||||
- VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0,
|
||||
- VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0);
|
||||
+ pred_weight_table->delta_luma_weight_l0,
|
||||
+ pred_weight_table->luma_offset_l0,
|
||||
+ pred_weight_table->delta_chroma_weight_l0,
|
||||
+ pred_weight_table->chroma_offset_l0,
|
||||
+ slice_params->num_ref_idx_l0_active_minus1 + 1,
|
||||
+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0,
|
||||
+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0);
|
||||
}
|
||||
|
||||
/* Reference picture list 1 (for B frames). */
|
||||
if (slice_params->slice_type == V4L2_HEVC_SLICE_TYPE_B) {
|
||||
cedrus_h265_ref_pic_list_write(dev, slice_params->dpb,
|
||||
slice_params->ref_idx_l1,
|
||||
- slice_params->num_ref_idx_l1_active_minus1 + 1,
|
||||
- VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1);
|
||||
+ slice_params->num_ref_idx_l1_active_minus1 + 1,
|
||||
+ VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1);
|
||||
|
||||
if (pps->weighted_bipred_flag)
|
||||
cedrus_h265_pred_weight_write(dev,
|
||||
- pred_weight_table->delta_luma_weight_l1,
|
||||
- pred_weight_table->luma_offset_l1,
|
||||
- pred_weight_table->delta_chroma_weight_l1,
|
||||
- pred_weight_table->chroma_offset_l1,
|
||||
- slice_params->num_ref_idx_l1_active_minus1 + 1,
|
||||
- VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1,
|
||||
- VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1);
|
||||
+ pred_weight_table->delta_luma_weight_l1,
|
||||
+ pred_weight_table->luma_offset_l1,
|
||||
+ pred_weight_table->delta_chroma_weight_l1,
|
||||
+ pred_weight_table->chroma_offset_l1,
|
||||
+ slice_params->num_ref_idx_l1_active_minus1 + 1,
|
||||
+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1,
|
||||
+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1);
|
||||
}
|
||||
|
||||
/* Enable appropriate interruptions. */
|
||||
@@ -484,9 +625,6 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx)
|
||||
{
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
|
||||
- /* The buffer size is calculated at setup time. */
|
||||
- ctx->codec.h265.mv_col_buf_size = 0;
|
||||
-
|
||||
ctx->codec.h265.neighbor_info_buf =
|
||||
dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
|
||||
&ctx->codec.h265.neighbor_info_buf_addr,
|
||||
@@ -494,6 +632,17 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx)
|
||||
if (!ctx->codec.h265.neighbor_info_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
+ ctx->codec.h265.entry_points_buf =
|
||||
+ dma_alloc_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE,
|
||||
+ &ctx->codec.h265.entry_points_buf_addr,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!ctx->codec.h265.entry_points_buf) {
|
||||
+ dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
|
||||
+ ctx->codec.h265.neighbor_info_buf,
|
||||
+ ctx->codec.h265.neighbor_info_buf_addr);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -501,17 +650,12 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx)
|
||||
{
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
|
||||
- if (ctx->codec.h265.mv_col_buf_size > 0) {
|
||||
- dma_free_coherent(dev->dev, ctx->codec.h265.mv_col_buf_size,
|
||||
- ctx->codec.h265.mv_col_buf,
|
||||
- ctx->codec.h265.mv_col_buf_addr);
|
||||
-
|
||||
- ctx->codec.h265.mv_col_buf_size = 0;
|
||||
- }
|
||||
-
|
||||
dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
|
||||
ctx->codec.h265.neighbor_info_buf,
|
||||
ctx->codec.h265.neighbor_info_buf_addr);
|
||||
+ dma_free_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE,
|
||||
+ ctx->codec.h265.entry_points_buf,
|
||||
+ ctx->codec.h265.entry_points_buf_addr);
|
||||
}
|
||||
|
||||
static void cedrus_h265_trigger(struct cedrus_ctx *ctx)
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
||||
index 87651d6b6227..8d153dbe4f83 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
||||
@@ -496,6 +496,9 @@
|
||||
#define VE_DEC_H265_TILE_START_CTB (VE_ENGINE_DEC_H265 + 0x68)
|
||||
#define VE_DEC_H265_TILE_END_CTB (VE_ENGINE_DEC_H265 + 0x6c)
|
||||
|
||||
+#define VE_DEC_H265_SCALING_LIST_DC_COEF0 (VE_ENGINE_DEC_H265 + 0x78)
|
||||
+#define VE_DEC_H265_SCALING_LIST_DC_COEF1 (VE_ENGINE_DEC_H265 + 0x7c)
|
||||
+
|
||||
#define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80)
|
||||
|
||||
#define VE_DEC_H265_LOW_ADDR_PRIMARY_CHROMA(a) \
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
||||
index dbe6f9510641..a0817cae1d69 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
||||
@@ -433,6 +433,24 @@ static void cedrus_queue_cleanup(struct vb2_queue *vq, u32 state)
|
||||
}
|
||||
}
|
||||
|
||||
+static void cedrus_buf_cleanup(struct vb2_buffer *vb)
|
||||
+{
|
||||
+ struct vb2_queue *vq = vb->vb2_queue;
|
||||
+ struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
|
||||
+
|
||||
+ if (!V4L2_TYPE_IS_OUTPUT(vq->type)) {
|
||||
+ struct cedrus_buffer *cedrus_buf;
|
||||
+
|
||||
+ cedrus_buf = vb2_to_cedrus_buffer(vq->bufs[vb->index]);
|
||||
+
|
||||
+ if (cedrus_buf->mv_col_buf_size)
|
||||
+ dma_free_coherent(ctx->dev->dev,
|
||||
+ cedrus_buf->mv_col_buf_size,
|
||||
+ cedrus_buf->mv_col_buf,
|
||||
+ cedrus_buf->mv_col_buf_dma);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int cedrus_buf_out_validate(struct vb2_buffer *vb)
|
||||
{
|
||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||
@@ -517,6 +497,7 @@ static void cedrus_buf_request_complete(struct vb2_buffer *vb)
|
||||
static struct vb2_ops cedrus_qops = {
|
||||
.queue_setup = cedrus_queue_setup,
|
||||
.buf_prepare = cedrus_buf_prepare,
|
||||
+ .buf_cleanup = cedrus_buf_cleanup,
|
||||
.buf_queue = cedrus_buf_queue,
|
||||
.buf_out_validate = cedrus_buf_out_validate,
|
||||
.buf_request_complete = cedrus_buf_request_complete,
|
||||
diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h
|
||||
index 2de83d9f6d47..19469097c6d4 100644
|
||||
--- a/include/media/hevc-ctrls.h
|
||||
+++ b/include/media/hevc-ctrls.h
|
||||
@@ -17,11 +17,13 @@
|
||||
#define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008)
|
||||
#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009)
|
||||
#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010)
|
||||
+#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 1011)
|
||||
|
||||
/* enum v4l2_ctrl_type type values */
|
||||
#define V4L2_CTRL_TYPE_HEVC_SPS 0x0120
|
||||
#define V4L2_CTRL_TYPE_HEVC_PPS 0x0121
|
||||
#define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122
|
||||
+#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123
|
||||
|
||||
#define V4L2_HEVC_SLICE_TYPE_B 0
|
||||
#define V4L2_HEVC_SLICE_TYPE_P 1
|
||||
@@ -95,7 +97,7 @@ struct v4l2_ctrl_hevc_pps {
|
||||
__u8 lists_modification_present_flag;
|
||||
__u8 log2_parallel_merge_level_minus2;
|
||||
__u8 slice_segment_header_extension_present_flag;
|
||||
- __u8 padding;
|
||||
+ __u8 scaling_list_enable_flag;
|
||||
};
|
||||
|
||||
#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE 0x01
|
||||
@@ -179,7 +181,21 @@ struct v4l2_ctrl_hevc_slice_params {
|
||||
/* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */
|
||||
struct v4l2_hevc_pred_weight_table pred_weight_table;
|
||||
|
||||
- __u8 padding[2];
|
||||
+ __u32 slice_segment_addr;
|
||||
+ __u32 num_entry_point_offsets;
|
||||
+ __u32 entry_point_offset_minus1[256];
|
||||
+ __u8 first_slice_segment_in_pic_flag;
|
||||
+
|
||||
+ __u8 padding;
|
||||
+};
|
||||
+
|
||||
+struct v4l2_ctrl_hevc_scaling_matrix {
|
||||
+ __u8 scaling_list_4x4[6][16];
|
||||
+ __u8 scaling_list_8x8[6][64];
|
||||
+ __u8 scaling_list_16x16[6][64];
|
||||
+ __u8 scaling_list_32x32[2][64];
|
||||
+ __u8 scaling_list_dc_coef_16x16[6];
|
||||
+ __u8 scaling_list_dc_coef_32x32[2];
|
||||
};
|
||||
|
||||
#endif
|
||||
--
|
||||
2.21.0
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
||||
index 2f017a651848..7ca216591c9c 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
||||
@@ -179,12 +179,16 @@ static inline dma_addr_t cedrus_buf_addr(struct vb2_buffer *buf,
|
||||
static inline dma_addr_t cedrus_dst_buf_addr(struct cedrus_ctx *ctx,
|
||||
int index, unsigned int plane)
|
||||
{
|
||||
- struct vb2_buffer *buf;
|
||||
+ struct vb2_buffer *buf = NULL;
|
||||
+ struct vb2_queue *vq;
|
||||
|
||||
if (index < 0)
|
||||
return 0;
|
||||
|
||||
- buf = ctx->fh.m2m_ctx->cap_q_ctx.q.bufs[index];
|
||||
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
||||
+ if (vq)
|
||||
+ buf = vb2_get_buffer(vq, index);
|
||||
+
|
||||
return buf ? cedrus_buf_addr(buf, &ctx->dst_fmt, plane) : 0;
|
||||
}
|
||||
|
@ -1,349 +0,0 @@
|
||||
From 6a900f36a70f921886f05373846368ca6f09446e Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sat, 25 May 2019 14:16:55 +0200
|
||||
Subject: [PATCH 5/5] cedrus h264 4k
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
drivers/staging/media/sunxi/cedrus/cedrus.h | 12 +-
|
||||
.../staging/media/sunxi/cedrus/cedrus_h264.c | 117 +++++++++++-------
|
||||
.../staging/media/sunxi/cedrus/cedrus_h265.c | 4 +-
|
||||
.../staging/media/sunxi/cedrus/cedrus_hw.c | 11 +-
|
||||
.../staging/media/sunxi/cedrus/cedrus_hw.h | 3 +-
|
||||
.../staging/media/sunxi/cedrus/cedrus_mpeg2.c | 2 +-
|
||||
.../staging/media/sunxi/cedrus/cedrus_regs.h | 4 +
|
||||
.../staging/media/sunxi/cedrus/cedrus_video.c | 4 +-
|
||||
8 files changed, 98 insertions(+), 59 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
||||
index b518c5613fdf..ee00449d3345 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
||||
@@ -118,14 +118,18 @@ struct cedrus_ctx {
|
||||
|
||||
union {
|
||||
struct {
|
||||
- void *mv_col_buf;
|
||||
- dma_addr_t mv_col_buf_dma;
|
||||
- ssize_t mv_col_buf_field_size;
|
||||
- ssize_t mv_col_buf_size;
|
||||
void *pic_info_buf;
|
||||
dma_addr_t pic_info_buf_dma;
|
||||
void *neighbor_info_buf;
|
||||
dma_addr_t neighbor_info_buf_dma;
|
||||
+
|
||||
+ void *deblk_buf;
|
||||
+ dma_addr_t deblk_buf_dma;
|
||||
+ ssize_t deblk_buf_size;
|
||||
+
|
||||
+ void *intra_pred_buf;
|
||||
+ dma_addr_t intra_pred_buf_dma;
|
||||
+ ssize_t intra_pred_buf_size;
|
||||
} h264;
|
||||
struct {
|
||||
void *neighbor_info_buf;
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
||||
index dcb8d3837869..4fafaf2c6c0a 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
||||
@@ -55,16 +55,14 @@ static void cedrus_h264_write_sram(struct cedrus_dev *dev,
|
||||
}
|
||||
|
||||
static dma_addr_t cedrus_h264_mv_col_buf_addr(struct cedrus_ctx *ctx,
|
||||
- unsigned int position,
|
||||
+ struct cedrus_buffer *buf,
|
||||
unsigned int field)
|
||||
{
|
||||
- dma_addr_t addr = ctx->codec.h264.mv_col_buf_dma;
|
||||
-
|
||||
- /* Adjust for the position */
|
||||
- addr += position * ctx->codec.h264.mv_col_buf_field_size * 2;
|
||||
+ dma_addr_t addr = buf->mv_col_buf_dma;
|
||||
|
||||
/* Adjust for the field */
|
||||
- addr += field * ctx->codec.h264.mv_col_buf_field_size;
|
||||
+ if (field)
|
||||
+ addr += buf->mv_col_buf_size / 2;
|
||||
|
||||
return addr;
|
||||
}
|
||||
@@ -76,7 +74,6 @@ static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx,
|
||||
struct cedrus_h264_sram_ref_pic *pic)
|
||||
{
|
||||
struct vb2_buffer *vbuf = &buf->m2m_buf.vb.vb2_buf;
|
||||
- unsigned int position = buf->codec.h264.position;
|
||||
|
||||
pic->top_field_order_cnt = cpu_to_le32(top_field_order_cnt);
|
||||
pic->bottom_field_order_cnt = cpu_to_le32(bottom_field_order_cnt);
|
||||
@@ -85,9 +82,9 @@ static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx,
|
||||
pic->luma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 0));
|
||||
pic->chroma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, &ctx->dst_fmt, 1));
|
||||
pic->mv_col_top_ptr =
|
||||
- cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 0));
|
||||
+ cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, buf, 0));
|
||||
pic->mv_col_bot_ptr =
|
||||
- cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 1));
|
||||
+ cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, buf, 1));
|
||||
}
|
||||
|
||||
static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
|
||||
@@ -145,6 +142,28 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
|
||||
output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf);
|
||||
output_buf->codec.h264.position = position;
|
||||
|
||||
+ if (!output_buf->mv_col_buf_size) {
|
||||
+ const struct v4l2_ctrl_h264_sps *sps = run->h264.sps;
|
||||
+ unsigned int field_size;
|
||||
+
|
||||
+ field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) *
|
||||
+ DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16;
|
||||
+ if (!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE))
|
||||
+ field_size = field_size * 2;
|
||||
+ if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY))
|
||||
+ field_size = field_size * 2;
|
||||
+
|
||||
+ output_buf->mv_col_buf_size = field_size * 2;
|
||||
+ output_buf->mv_col_buf =
|
||||
+ dma_alloc_coherent(dev->dev,
|
||||
+ output_buf->mv_col_buf_size,
|
||||
+ &output_buf->mv_col_buf_dma,
|
||||
+ GFP_KERNEL);
|
||||
+
|
||||
+ if (!output_buf->mv_col_buf)
|
||||
+ output_buf->mv_col_buf_size = 0;
|
||||
+ }
|
||||
+
|
||||
if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)
|
||||
output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FIELD;
|
||||
else if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)
|
||||
@@ -338,6 +357,14 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
||||
VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID |
|
||||
VE_H264_VLD_ADDR_LAST);
|
||||
|
||||
+ if (((sps->pic_width_in_mbs_minus1 + 1) * 16) > 2048) {
|
||||
+ cedrus_write(dev, VE_DBLK_INTRAPRED_BUF_CTRL, 0x5);
|
||||
+ cedrus_write(dev, VE_DBLK_DRAM_BUF_ADDR,
|
||||
+ ctx->codec.h264.deblk_buf_dma);
|
||||
+ cedrus_write(dev, VE_INTRAPRED_DRAM_BUF_ADDR,
|
||||
+ ctx->codec.h264.intra_pred_buf_dma);
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* FIXME: Since the bitstream parsing is done in software, and
|
||||
* in userspace, this shouldn't be needed anymore. But it
|
||||
@@ -476,7 +503,8 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx,
|
||||
{
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
|
||||
- cedrus_engine_enable(dev, CEDRUS_CODEC_H264);
|
||||
+ cedrus_engine_enable(dev, CEDRUS_CODEC_H264,
|
||||
+ ctx->src_fmt.width);
|
||||
|
||||
cedrus_write(dev, VE_H264_SDROT_CTRL, 0);
|
||||
cedrus_write(dev, VE_H264_EXTRA_BUFFER1,
|
||||
@@ -493,8 +521,6 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx,
|
||||
static int cedrus_h264_start(struct cedrus_ctx *ctx)
|
||||
{
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
- unsigned int field_size;
|
||||
- unsigned int mv_col_size;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@@ -526,44 +552,42 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx)
|
||||
goto err_pic_buf;
|
||||
}
|
||||
|
||||
- field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) *
|
||||
- DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16;
|
||||
-
|
||||
- /*
|
||||
- * FIXME: This is actually conditional to
|
||||
- * V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE not being set, we
|
||||
- * might have to rework this if memory efficiency ever is
|
||||
- * something we need to work on.
|
||||
- */
|
||||
- field_size = field_size * 2;
|
||||
+ if (ctx->src_fmt.width > 2048) {
|
||||
+ ctx->codec.h264.deblk_buf_size =
|
||||
+ ALIGN(ctx->src_fmt.width, 32) * 12;
|
||||
+ ctx->codec.h264.deblk_buf =
|
||||
+ dma_alloc_coherent(dev->dev,
|
||||
+ ctx->codec.h264.deblk_buf_size,
|
||||
+ &ctx->codec.h264.deblk_buf_dma,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!ctx->codec.h264.deblk_buf) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_neighbor_buf;
|
||||
+ }
|
||||
|
||||
- /*
|
||||
- * FIXME: This is actually conditional to
|
||||
- * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY not being set, we might
|
||||
- * have to rework this if memory efficiency ever is something
|
||||
- * we need to work on.
|
||||
- */
|
||||
- field_size = field_size * 2;
|
||||
- ctx->codec.h264.mv_col_buf_field_size = field_size;
|
||||
-
|
||||
- mv_col_size = field_size * 2 * CEDRUS_H264_FRAME_NUM;
|
||||
- ctx->codec.h264.mv_col_buf_size = mv_col_size;
|
||||
- ctx->codec.h264.mv_col_buf = dma_alloc_coherent(dev->dev,
|
||||
- ctx->codec.h264.mv_col_buf_size,
|
||||
- &ctx->codec.h264.mv_col_buf_dma,
|
||||
- GFP_KERNEL);
|
||||
- if (!ctx->codec.h264.mv_col_buf) {
|
||||
- ret = -ENOMEM;
|
||||
- goto err_neighbor_buf;
|
||||
+ ctx->codec.h264.intra_pred_buf_size =
|
||||
+ ALIGN(ctx->src_fmt.width, 64) * 5;
|
||||
+ ctx->codec.h264.intra_pred_buf =
|
||||
+ dma_alloc_coherent(dev->dev,
|
||||
+ ctx->codec.h264.intra_pred_buf_size,
|
||||
+ &ctx->codec.h264.intra_pred_buf_dma,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!ctx->codec.h264.intra_pred_buf) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_deblk_buf;
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+err_deblk_buf:
|
||||
+ dma_free_coherent(dev->dev, ctx->codec.h264.deblk_buf_size,
|
||||
+ ctx->codec.h264.deblk_buf,
|
||||
+ ctx->codec.h264.deblk_buf_dma);
|
||||
err_neighbor_buf:
|
||||
dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE,
|
||||
ctx->codec.h264.neighbor_info_buf,
|
||||
ctx->codec.h264.neighbor_info_buf_dma);
|
||||
-
|
||||
err_pic_buf:
|
||||
dma_free_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE,
|
||||
ctx->codec.h264.pic_info_buf,
|
||||
@@ -575,15 +599,20 @@ static void cedrus_h264_stop(struct cedrus_ctx *ctx)
|
||||
{
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
|
||||
- dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size,
|
||||
- ctx->codec.h264.mv_col_buf,
|
||||
- ctx->codec.h264.mv_col_buf_dma);
|
||||
dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE,
|
||||
ctx->codec.h264.neighbor_info_buf,
|
||||
ctx->codec.h264.neighbor_info_buf_dma);
|
||||
dma_free_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE,
|
||||
ctx->codec.h264.pic_info_buf,
|
||||
ctx->codec.h264.pic_info_buf_dma);
|
||||
+ if (ctx->codec.h264.deblk_buf_size)
|
||||
+ dma_free_coherent(dev->dev, ctx->codec.h264.deblk_buf_size,
|
||||
+ ctx->codec.h264.deblk_buf,
|
||||
+ ctx->codec.h264.deblk_buf_dma);
|
||||
+ if (ctx->codec.h264.intra_pred_buf_size)
|
||||
+ dma_free_coherent(dev->dev, ctx->codec.h264.intra_pred_buf_size,
|
||||
+ ctx->codec.h264.intra_pred_buf,
|
||||
+ ctx->codec.h264.intra_pred_buf_dma);
|
||||
}
|
||||
|
||||
static void cedrus_h264_trigger(struct cedrus_ctx *ctx)
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||
index 51ee459b2d21..f915429e9c88 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
||||
@@ -337,9 +337,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
pred_weight_table = &slice_params->pred_weight_table;
|
||||
|
||||
/* Activate H265 engine. */
|
||||
- cedrus_engine_enable(dev, CEDRUS_CODEC_H265);
|
||||
- if (sps->pic_width_in_luma_samples > 2048)
|
||||
- cedrus_write(dev, VE_MODE, cedrus_read(dev, VE_MODE) | BIT(21));
|
||||
+ cedrus_engine_enable(dev, CEDRUS_CODEC_H265, ctx->src_fmt.width);
|
||||
|
||||
/* Source offset and length in bits. */
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
|
||||
index 7d2f6eedfc28..9503d395855b 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
|
||||
@@ -30,7 +30,8 @@
|
||||
#include "cedrus_hw.h"
|
||||
#include "cedrus_regs.h"
|
||||
|
||||
-int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec)
|
||||
+int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec,
|
||||
+ unsigned int width)
|
||||
{
|
||||
u32 reg = 0;
|
||||
|
||||
@@ -58,6 +59,11 @@ int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ if (width >= 4096)
|
||||
+ reg |= BIT(22);
|
||||
+ if (width > 2048)
|
||||
+ reg |= BIT(21);
|
||||
+
|
||||
cedrus_write(dev, VE_MODE, reg);
|
||||
|
||||
return 0;
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
|
||||
index 27d0882397aa..0e67c69812be 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
|
||||
@@ -16,7 +16,8 @@
|
||||
#ifndef _CEDRUS_HW_H_
|
||||
#define _CEDRUS_HW_H_
|
||||
|
||||
-int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec);
|
||||
+int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec,
|
||||
+ unsigned int width);
|
||||
void cedrus_engine_disable(struct cedrus_dev *dev);
|
||||
|
||||
void cedrus_dst_format_set(struct cedrus_dev *dev,
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
|
||||
index 13c34927bad5..fc00a2cbf9bf 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
|
||||
@@ -96,7 +96,7 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
|
||||
quantization = run->mpeg2.quantization;
|
||||
|
||||
/* Activate MPEG engine. */
|
||||
- cedrus_engine_enable(dev, CEDRUS_CODEC_MPEG2);
|
||||
+ cedrus_engine_enable(dev, CEDRUS_CODEC_MPEG2, ctx->src_fmt.width);
|
||||
|
||||
/* Set intra quantization matrix. */
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
||||
index a2931f322c7a..df000b7c99be 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
||||
@@ -41,6 +41,10 @@
|
||||
#define VE_MODE_DEC_H264 (0x01 << 0)
|
||||
#define VE_MODE_DEC_MPEG (0x00 << 0)
|
||||
|
||||
+#define VE_DBLK_INTRAPRED_BUF_CTRL 0x50
|
||||
+#define VE_DBLK_DRAM_BUF_ADDR 0x54
|
||||
+#define VE_INTRAPRED_DRAM_BUF_ADDR 0x58
|
||||
+
|
||||
#define VE_PRIMARY_CHROMA_BUF_LEN 0xc4
|
||||
#define VE_PRIMARY_FB_LINE_STRIDE 0xc8
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
||||
index a0817cae1d69..d27a9e82ff91 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
#define CEDRUS_MIN_WIDTH 16U
|
||||
#define CEDRUS_MIN_HEIGHT 16U
|
||||
-#define CEDRUS_MAX_WIDTH 3840U
|
||||
-#define CEDRUS_MAX_HEIGHT 2160U
|
||||
+#define CEDRUS_MAX_WIDTH 4096U
|
||||
+#define CEDRUS_MAX_HEIGHT 2768U
|
||||
|
||||
static struct cedrus_format cedrus_formats[] = {
|
||||
{
|
||||
--
|
||||
2.21.0
|
||||
|
Loading…
x
Reference in New Issue
Block a user