mirror of
https://github.com/Fishwaldo/build.git
synced 2025-04-30 12:11:26 +00:00
* [Allwinner] Add analogue audio to H6, enable Cedrus, remove deprecated patches, adjust config * Cleanup
1395 lines
51 KiB
Diff
1395 lines
51 KiB
Diff
From 4d25b2ae236bf42f5f9ef1d57cbc2523222a4422 Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Sat, 26 Oct 2019 13:55:15 +0200
|
|
Subject: [PATCH 04/14] media: uapi: hevc: Add scaling matrix control
|
|
|
|
HEVC has a scaling matrix concept. Add support for it.
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
.../media/uapi/v4l/ext-ctrls-codec.rst | 41 +++++++++++++++++++
|
|
.../media/uapi/v4l/pixfmt-compressed.rst | 1 +
|
|
drivers/media/v4l2-core/v4l2-ctrls.c | 10 +++++
|
|
include/media/hevc-ctrls.h | 11 +++++
|
|
4 files changed, 63 insertions(+)
|
|
|
|
diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
|
|
index a1209f68c5e8..382e85e16444 100644
|
|
--- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
|
|
@@ -4176,6 +4176,47 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
|
|
- ``padding[6]``
|
|
- Applications and drivers must set this to zero.
|
|
|
|
+``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (struct)``
|
|
+ Specifies the scaling matrix (as extracted from the bitstream) for
|
|
+ the associated HEVC slice data. The bitstream parameters are
|
|
+ defined according to :ref:`hevc`, section 7.4.5 "Scaling list
|
|
+ data semantics". For further documentation, refer to the above
|
|
+ specification, unless there is an explicit comment stating
|
|
+ otherwise.
|
|
+
|
|
+ .. note::
|
|
+
|
|
+ This compound control is not yet part of the public kernel API and
|
|
+ it is expected to change.
|
|
+
|
|
+.. c:type:: v4l2_ctrl_hevc_scaling_matrix
|
|
+
|
|
+.. cssclass:: longtable
|
|
+
|
|
+.. flat-table:: struct v4l2_ctrl_hevc_scaling_matrix
|
|
+ :header-rows: 0
|
|
+ :stub-columns: 0
|
|
+ :widths: 1 1 2
|
|
+
|
|
+ * - __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]``
|
|
+ -
|
|
+
|
|
``V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (enum)``
|
|
Specifies the decoding mode to use. Currently exposes slice-based and
|
|
frame-based decoding but new modes might be added later on.
|
|
|
|
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
index b4caf2d4d076..2803165cbc6a 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
|
|
@@ -975,6 +975,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";
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: return "HEVC Decode Mode";
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: return "HEVC Start Code";
|
|
|
|
@@ -1407,6 +1408,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;
|
|
case V4L2_CID_UNIT_CELL_SIZE:
|
|
*type = V4L2_CTRL_TYPE_AREA;
|
|
*flags |= V4L2_CTRL_FLAG_READ_ONLY;
|
|
@@ -1856,6 +1860,9 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
|
|
zero_padding(*p_hevc_slice_params);
|
|
break;
|
|
|
|
+ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX:
|
|
+ break;
|
|
+
|
|
case V4L2_CTRL_TYPE_AREA:
|
|
area = p;
|
|
if (!area->width || !area->height)
|
|
@@ -2545,6 +2552,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;
|
|
case V4L2_CTRL_TYPE_AREA:
|
|
elem_size = sizeof(struct v4l2_area);
|
|
break;
|
|
diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h
|
|
index 1009cf0891cc..1592e52c3614 100644
|
|
--- a/include/media/hevc-ctrls.h
|
|
+++ b/include/media/hevc-ctrls.h
|
|
@@ -19,6 +19,7 @@
|
|
#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)
|
|
#define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (V4L2_CID_MPEG_BASE + 1015)
|
|
#define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE (V4L2_CID_MPEG_BASE + 1016)
|
|
|
|
@@ -26,6 +27,7 @@
|
|
#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
|
|
|
|
enum v4l2_mpeg_video_hevc_decode_mode {
|
|
V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED,
|
|
@@ -209,4 +211,13 @@ struct v4l2_ctrl_hevc_slice_params {
|
|
__u64 flags;
|
|
};
|
|
|
|
+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.24.0
|
|
|
|
|
|
From 000a33e20cc53fa82e3bc116d411135e93d5ab95 Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Sat, 26 Oct 2019 13:58:49 +0200
|
|
Subject: [PATCH 05/14] media: cedrus: hevc: Add support for scaling matrix
|
|
|
|
HEVC frames may use scaling list feature. Add support for it.
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
drivers/staging/media/sunxi/cedrus/cedrus.c | 7 ++
|
|
drivers/staging/media/sunxi/cedrus/cedrus.h | 1 +
|
|
.../staging/media/sunxi/cedrus/cedrus_dec.c | 2 +
|
|
.../staging/media/sunxi/cedrus/cedrus_h265.c | 70 ++++++++++++++++++-
|
|
.../staging/media/sunxi/cedrus/cedrus_regs.h | 2 +
|
|
5 files changed, 81 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
|
index c6ddd46eff82..bf68bc6b20c8 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
|
@@ -116,6 +116,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,
|
|
+ },
|
|
{
|
|
.cfg = {
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE,
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
index 96765555ab8a..d945f4f0ff2d 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
@@ -73,6 +73,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 {
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
|
|
index 4a2fc33a1d79..327ed6c264dc 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 6945dc74e1d7..888bfd5ca224 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
@@ -220,6 +220,69 @@ 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 cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
struct cedrus_run *run)
|
|
{
|
|
@@ -499,7 +562,12 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
|
|
/* Scaling list. */
|
|
|
|
- reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT;
|
|
+ if (sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) {
|
|
+ cedrus_h265_write_scaling_list(ctx, run);
|
|
+ reg = VE_DEC_H265_SCALING_LIST_CTRL0_FLAG_ENABLED;
|
|
+ } else {
|
|
+ reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT;
|
|
+ }
|
|
cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg);
|
|
|
|
/* Neightbor information address. */
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
|
index 7beb03d3bb39..0d9449fe2b28 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
|
@@ -492,6 +492,8 @@
|
|
#define VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR (VE_ENGINE_DEC_H265 + 0x64)
|
|
#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)
|
|
|
|
--
|
|
2.24.0
|
|
|
|
|
|
From 48f70ba58e4df3bd9b9cb9c7969ba93f95e25e75 Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Sat, 26 Oct 2019 15:42:28 +0200
|
|
Subject: [PATCH 06/14] media: uapi: hevc: Add segment address field
|
|
|
|
If HEVC frame consists of multiple slices, segment address has to be
|
|
known in order to properly decode it.
|
|
|
|
Add segment address field to slice parameters.
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
Documentation/media/uapi/v4l/ext-ctrls-codec.rst | 5 ++++-
|
|
include/media/hevc-ctrls.h | 5 ++++-
|
|
2 files changed, 8 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
|
|
index 382e85e16444..99e4a7099614 100644
|
|
--- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
|
|
@@ -3971,6 +3971,9 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
|
|
* - __u32
|
|
- ``data_bit_offset``
|
|
- Offset (in bits) to the video data in the current slice data.
|
|
+ * - __u32
|
|
+ - ``slice_segment_addr``
|
|
+ -
|
|
* - __u8
|
|
- ``nal_unit_type``
|
|
-
|
|
@@ -4048,7 +4051,7 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
|
|
- ``num_rps_poc_lt_curr``
|
|
- The number of reference pictures in the long-term set.
|
|
* - __u8
|
|
- - ``padding[7]``
|
|
+ - ``padding[5]``
|
|
- Applications and drivers must set this to zero.
|
|
* - struct :c:type:`v4l2_hevc_dpb_entry`
|
|
- ``dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]``
|
|
diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h
|
|
index 1592e52c3614..3e2e32098312 100644
|
|
--- a/include/media/hevc-ctrls.h
|
|
+++ b/include/media/hevc-ctrls.h
|
|
@@ -167,6 +167,9 @@ struct v4l2_ctrl_hevc_slice_params {
|
|
__u32 bit_size;
|
|
__u32 data_bit_offset;
|
|
|
|
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
|
|
+ __u32 slice_segment_addr;
|
|
+
|
|
/* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
|
|
__u8 nal_unit_type;
|
|
__u8 nuh_temporal_id_plus1;
|
|
@@ -200,7 +203,7 @@ struct v4l2_ctrl_hevc_slice_params {
|
|
__u8 num_rps_poc_st_curr_after;
|
|
__u8 num_rps_poc_lt_curr;
|
|
|
|
- __u8 padding;
|
|
+ __u8 padding[5];
|
|
|
|
/* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
|
|
struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
|
|
--
|
|
2.24.0
|
|
|
|
|
|
From 468a7019d3475a6dbdf368519c75f9e6625f2a1a Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Sat, 26 Oct 2019 15:44:15 +0200
|
|
Subject: [PATCH 07/14] media: cedrus: hevc: Add support for multiple slices
|
|
|
|
Now that segment address is available, support for multi-slice frames
|
|
can be easily added.
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
.../staging/media/sunxi/cedrus/cedrus_h265.c | 26 ++++++++++++-------
|
|
.../staging/media/sunxi/cedrus/cedrus_video.c | 1 +
|
|
2 files changed, 17 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
index 888bfd5ca224..109d3289418c 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
@@ -291,6 +291,8 @@ 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;
|
|
+ unsigned int width_in_ctb_luma, ctb_size_luma;
|
|
+ unsigned int log2_max_luma_coding_block_size;
|
|
dma_addr_t src_buf_addr;
|
|
dma_addr_t src_buf_end_addr;
|
|
u32 chroma_log2_weight_denom;
|
|
@@ -303,15 +305,17 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
slice_params = run->h265.slice_params;
|
|
pred_weight_table = &slice_params->pred_weight_table;
|
|
|
|
+ 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 = 1UL << log2_max_luma_coding_block_size;
|
|
+ width_in_ctb_luma =
|
|
+ DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
|
|
+
|
|
/* 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 =
|
|
- 1UL << log2_max_luma_coding_block_size;
|
|
|
|
/*
|
|
* Each CTB requires a MV col buffer with a specific unit size.
|
|
@@ -366,15 +370,17 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr);
|
|
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);
|
|
+ /* Coding tree block address */
|
|
+ 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);
|
|
|
|
cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
|
|
cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
|
|
|
|
/* Clear the number of correctly-decoded coding tree blocks. */
|
|
- cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
|
|
+ if (ctx->fh.m2m_ctx->new_frame)
|
|
+ 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);
|
|
@@ -523,8 +529,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT,
|
|
pps->flags);
|
|
|
|
- /* FIXME: For multi-slice support. */
|
|
- reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
|
|
+ if (ctx->fh.m2m_ctx->new_frame)
|
|
+ reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
|
|
|
|
cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg);
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
|
index 15cf1f10221b..497b1199d3fe 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
|
@@ -311,6 +311,7 @@ static int cedrus_s_fmt_vid_out(struct file *file, void *priv,
|
|
|
|
switch (ctx->src_fmt.pixelformat) {
|
|
case V4L2_PIX_FMT_H264_SLICE:
|
|
+ case V4L2_PIX_FMT_HEVC_SLICE:
|
|
vq->subsystem_flags |=
|
|
VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
|
|
break;
|
|
--
|
|
2.24.0
|
|
|
|
|
|
From 3be57e9b0d05bbe59aa60eb037d46b523a8a4103 Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Sun, 3 Nov 2019 12:36:52 +0100
|
|
Subject: [PATCH 08/14] media: cedrus: Fix decoding for some HEVC videos
|
|
|
|
It seems that for some HEVC 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 several videos
|
|
with this fix are now decoded correctly and there is no regression with
|
|
others.
|
|
|
|
Without this fix, those same videos totaly crash HEVC decoder (others
|
|
are unaffected). After decoding those problematic videos, HEVC decoder
|
|
always returns only green image (all zeros). Only complete HW reset
|
|
helps.
|
|
|
|
This fix is similar to that for H264.
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
.../staging/media/sunxi/cedrus/cedrus_h265.c | 25 ++++++++++++++++---
|
|
.../staging/media/sunxi/cedrus/cedrus_regs.h | 1 +
|
|
2 files changed, 23 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
index 109d3289418c..5a207f1e137c 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
@@ -7,6 +7,7 @@
|
|
* Copyright (C) 2018 Bootlin
|
|
*/
|
|
|
|
+#include <linux/delay.h>
|
|
#include <linux/types.h>
|
|
|
|
#include <media/videobuf2-dma-contig.h>
|
|
@@ -283,6 +284,23 @@ static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx,
|
|
}
|
|
}
|
|
|
|
+static void cedrus_h265_skip_bits(struct cedrus_dev *dev, int num)
|
|
+{
|
|
+ int count = 0;
|
|
+
|
|
+ while (count < num) {
|
|
+ int tmp = min(num - count, 32);
|
|
+
|
|
+ cedrus_write(dev, VE_DEC_H265_TRIGGER,
|
|
+ VE_DEC_H265_TRIGGER_FLUSH_BITS |
|
|
+ VE_DEC_H265_TRIGGER_TYPE_N_BITS(tmp));
|
|
+ while (cedrus_read(dev, VE_DEC_H265_STATUS) & VE_DEC_H265_STATUS_VLD_BUSY)
|
|
+ udelay(1);
|
|
+
|
|
+ count += tmp;
|
|
+ }
|
|
+}
|
|
+
|
|
static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
struct cedrus_run *run)
|
|
{
|
|
@@ -347,10 +365,9 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
|
|
/* Source offset and length in bits. */
|
|
|
|
- reg = slice_params->data_bit_offset;
|
|
- cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, reg);
|
|
+ cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, 0);
|
|
|
|
- reg = slice_params->bit_size - slice_params->data_bit_offset;
|
|
+ reg = slice_params->bit_size;
|
|
cedrus_write(dev, VE_DEC_H265_BITS_LEN, reg);
|
|
|
|
/* Source beginning and end addresses. */
|
|
@@ -385,6 +402,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
/* Initialize bitstream access. */
|
|
cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC);
|
|
|
|
+ cedrus_h265_skip_bits(dev, slice_params->data_bit_offset);
|
|
+
|
|
/* Bitstream parameters. */
|
|
|
|
reg = VE_DEC_H265_DEC_NAL_HDR_NAL_UNIT_TYPE(slice_params->nal_unit_type) |
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
|
index 0d9449fe2b28..df1cceef8d93 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
|
|
@@ -424,6 +424,7 @@
|
|
|
|
#define VE_DEC_H265_TRIGGER (VE_ENGINE_DEC_H265 + 0x34)
|
|
|
|
+#define VE_DEC_H265_TRIGGER_TYPE_N_BITS(x) (((x) & 0x3f) << 8)
|
|
#define VE_DEC_H265_TRIGGER_STCD_VC1 (0x02 << 4)
|
|
#define VE_DEC_H265_TRIGGER_STCD_AVS (0x01 << 4)
|
|
#define VE_DEC_H265_TRIGGER_STCD_HEVC (0x00 << 4)
|
|
--
|
|
2.24.0
|
|
|
|
|
|
From cf4ceb6095f67569dc22b09a150176d42ded09a5 Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Sat, 26 Oct 2019 21:23:55 +0200
|
|
Subject: [PATCH 09/14] media: cedrus: hevc: tiles hack
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
drivers/staging/media/sunxi/cedrus/cedrus.h | 2 +
|
|
.../staging/media/sunxi/cedrus/cedrus_h265.c | 93 +++++++++++++++++--
|
|
include/media/hevc-ctrls.h | 5 +-
|
|
3 files changed, 93 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
index d945f4f0ff2d..1204e32d83bc 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
@@ -134,6 +134,8 @@ struct cedrus_ctx {
|
|
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_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
index 5a207f1e137c..97dce6ffbbc5 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
@@ -284,6 +284,61 @@ static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx,
|
|
}
|
|
}
|
|
|
|
+static void write_entry_point_list(struct cedrus_ctx *ctx,
|
|
+ struct cedrus_run *run,
|
|
+ unsigned int ctb_addr_x,
|
|
+ unsigned int ctb_addr_y)
|
|
+{
|
|
+ const struct v4l2_ctrl_hevc_slice_params *slice_params;
|
|
+ const struct v4l2_ctrl_hevc_pps *pps;
|
|
+ struct cedrus_dev *dev = ctx->dev;
|
|
+ int i, x, tx, y, ty;
|
|
+ u32 *entry_points;
|
|
+
|
|
+ pps = run->h265.pps;
|
|
+ slice_params = run->h265.slice_params;
|
|
+
|
|
+ for (x = 0, tx = 0; tx < pps->num_tile_columns_minus1 + 1; tx++) {
|
|
+ if (x + pps->column_width_minus1[tx] + 1 > ctb_addr_x)
|
|
+ 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 > ctb_addr_y)
|
|
+ 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->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED) {
|
|
+ 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 = 0;
|
|
+ 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_skip_bits(struct cedrus_dev *dev, int num)
|
|
{
|
|
int count = 0;
|
|
@@ -311,6 +366,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
const struct v4l2_hevc_pred_weight_table *pred_weight_table;
|
|
unsigned int width_in_ctb_luma, ctb_size_luma;
|
|
unsigned int log2_max_luma_coding_block_size;
|
|
+ unsigned int ctb_addr_x, ctb_addr_y;
|
|
dma_addr_t src_buf_addr;
|
|
dma_addr_t src_buf_end_addr;
|
|
u32 chroma_log2_weight_denom;
|
|
@@ -388,12 +444,19 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg);
|
|
|
|
/* Coding tree block address */
|
|
- 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);
|
|
+ ctb_addr_x = slice_params->slice_segment_addr % width_in_ctb_luma;
|
|
+ ctb_addr_y = slice_params->slice_segment_addr / width_in_ctb_luma;
|
|
+ reg = VE_DEC_H265_DEC_CTB_ADDR_X(ctb_addr_x);
|
|
+ reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(ctb_addr_y);
|
|
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->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) ||
|
|
+ (pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED)) {
|
|
+ write_entry_point_list(ctx, run, ctb_addr_x, ctb_addr_y);
|
|
+ } else {
|
|
+ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
|
|
+ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
|
|
+ }
|
|
|
|
/* Clear the number of correctly-decoded coding tree blocks. */
|
|
if (ctx->fh.m2m_ctx->new_frame)
|
|
@@ -496,7 +559,9 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED,
|
|
pps->flags);
|
|
|
|
- /* TODO: VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED */
|
|
+ reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED,
|
|
+ V4L2_HEVC_PPS_FLAG_TILES_ENABLED,
|
|
+ pps->flags);
|
|
|
|
reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TRANSQUANT_BYPASS_ENABLED,
|
|
V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED,
|
|
@@ -572,12 +637,14 @@ 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) |
|
|
@@ -671,6 +738,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;
|
|
}
|
|
|
|
@@ -689,6 +767,9 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx)
|
|
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/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h
|
|
index 3e2e32098312..d1b094c8aaeb 100644
|
|
--- a/include/media/hevc-ctrls.h
|
|
+++ b/include/media/hevc-ctrls.h
|
|
@@ -169,6 +169,7 @@ struct v4l2_ctrl_hevc_slice_params {
|
|
|
|
/* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
|
|
__u32 slice_segment_addr;
|
|
+ __u32 num_entry_point_offsets;
|
|
|
|
/* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
|
|
__u8 nal_unit_type;
|
|
@@ -203,7 +204,9 @@ struct v4l2_ctrl_hevc_slice_params {
|
|
__u8 num_rps_poc_st_curr_after;
|
|
__u8 num_rps_poc_lt_curr;
|
|
|
|
- __u8 padding[5];
|
|
+ __u8 padding;
|
|
+
|
|
+ __u32 entry_point_offset_minus1[256];
|
|
|
|
/* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
|
|
struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
|
|
--
|
|
2.24.0
|
|
|
|
|
|
From 42b71243ef0c15e1d940583ef3fce99ec79a1975 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 10/14] media: cedrus: H264 interlace hack
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
.../staging/media/sunxi/cedrus/cedrus_h264.c | 24 ++++++++++++-------
|
|
1 file changed, 16 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
index ab83a6f1f921..b0ee4aed79f9 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
@@ -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;
|
|
|
|
cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
|
@@ -125,6 +125,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;
|
|
|
|
@@ -132,13 +137,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);
|
|
@@ -164,6 +167,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,
|
|
@@ -188,7 +195,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))
|
|
@@ -203,7 +210,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);
|
|
}
|
|
|
|
--
|
|
2.24.0
|
|
|
|
|
|
From 6c1b98710d93611eec39bbcfcf07b3fc48e11459 Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Sat, 9 Nov 2019 11:50:40 +0100
|
|
Subject: [PATCH 11/14] media: cedrus: hevc: Add luma bit depth
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
drivers/staging/media/sunxi/cedrus/cedrus_h265.c | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
index 97dce6ffbbc5..89e269cc066d 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
@@ -483,6 +483,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_CHROMA_FORMAT_IDC(sps->chroma_format_idc);
|
|
|
|
reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_STRONG_INTRA_SMOOTHING_ENABLE,
|
|
--
|
|
2.24.0
|
|
|
|
|
|
From 187e20b079317e312a1be425ff4c19f838b9e625 Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Sat, 9 Nov 2019 13:06:15 +0100
|
|
Subject: [PATCH 12/14] media: cedrus: Add callback for buffer cleanup
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
drivers/staging/media/sunxi/cedrus/cedrus.h | 1 +
|
|
drivers/staging/media/sunxi/cedrus/cedrus_video.c | 13 +++++++++++++
|
|
2 files changed, 14 insertions(+)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
index 1204e32d83bc..9298aa5f229d 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
@@ -148,6 +148,7 @@ struct cedrus_dec_ops {
|
|
int (*start)(struct cedrus_ctx *ctx);
|
|
void (*stop)(struct cedrus_ctx *ctx);
|
|
void (*trigger)(struct cedrus_ctx *ctx);
|
|
+ void (*buf_cleanup)(struct cedrus_ctx *ctx, struct cedrus_buffer *buf);
|
|
};
|
|
|
|
struct cedrus_variant {
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
|
index 497b1199d3fe..7f95216a552e 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
|
@@ -431,6 +431,18 @@ static int cedrus_buf_prepare(struct vb2_buffer *vb)
|
|
return 0;
|
|
}
|
|
|
|
+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);
|
|
+ struct cedrus_dev *dev = ctx->dev;
|
|
+ struct cedrus_dec_ops *ops = dev->dec_ops[ctx->current_codec];
|
|
+
|
|
+ if (!V4L2_TYPE_IS_OUTPUT(vq->type) && ops->buf_cleanup)
|
|
+ ops->buf_cleanup(ctx,
|
|
+ vb2_to_cedrus_buffer(vq->bufs[vb->index]));
|
|
+}
|
|
+
|
|
static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count)
|
|
{
|
|
struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
|
|
@@ -494,6 +506,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,
|
|
--
|
|
2.24.0
|
|
|
|
|
|
From 024630941ade1aa57b4c16a5577ee9cf4f62be18 Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Sat, 9 Nov 2019 13:22:05 +0100
|
|
Subject: [PATCH 13/14] media: cedrus: hevc: Improve buffer management
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
drivers/staging/media/sunxi/cedrus/cedrus.h | 9 +-
|
|
.../staging/media/sunxi/cedrus/cedrus_h265.c | 117 ++++++++++--------
|
|
2 files changed, 69 insertions(+), 57 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
index 9298aa5f229d..d8a4f8e83f94 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
@@ -95,6 +95,11 @@ struct cedrus_buffer {
|
|
unsigned int position;
|
|
enum cedrus_h264_pic_type pic_type;
|
|
} h264;
|
|
+ struct {
|
|
+ void *mv_col_buf;
|
|
+ dma_addr_t mv_col_buf_dma;
|
|
+ ssize_t mv_col_buf_size;
|
|
+ } h265;
|
|
} codec;
|
|
};
|
|
|
|
@@ -128,10 +133,6 @@ struct cedrus_ctx {
|
|
ssize_t intra_pred_buf_size;
|
|
} 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;
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
index 89e269cc066d..7c806ef6e8ef 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
@@ -91,26 +91,66 @@ static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data,
|
|
|
|
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,
|
|
+ const struct v4l2_ctrl_hevc_sps *sps)
|
|
{
|
|
- 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);
|
|
+
|
|
+ if (!cedrus_buf)
|
|
+ return 0;
|
|
+
|
|
+ if (!cedrus_buf->codec.h265.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->codec.h265.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->codec.h265.mv_col_buf =
|
|
+ dma_alloc_coherent(ctx->dev->dev,
|
|
+ cedrus_buf->codec.h265.mv_col_buf_size,
|
|
+ &cedrus_buf->codec.h265.mv_col_buf_dma,
|
|
+ GFP_KERNEL);
|
|
+
|
|
+ if (!cedrus_buf->codec.h265.mv_col_buf) {
|
|
+ cedrus_buf->codec.h265.mv_col_buf_size = 0;
|
|
+ cedrus_buf->codec.h265.mv_col_buf_dma = 0;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return cedrus_buf->codec.h265.mv_col_buf_dma;
|
|
}
|
|
|
|
static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
|
|
unsigned int index,
|
|
bool field_pic,
|
|
u32 pic_order_cnt[],
|
|
- int buffer_index)
|
|
+ int buffer_index,
|
|
+ const struct v4l2_ctrl_hevc_sps *sps)
|
|
{
|
|
struct cedrus_dev *dev = ctx->dev;
|
|
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, sps),
|
|
+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, sps)
|
|
};
|
|
u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO +
|
|
VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index;
|
|
@@ -134,7 +174,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
|
|
|
|
static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx,
|
|
const struct v4l2_hevc_dpb_entry *dpb,
|
|
- u8 num_active_dpb_entries)
|
|
+ u8 num_active_dpb_entries,
|
|
+ const struct v4l2_ctrl_hevc_sps *sps)
|
|
{
|
|
struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
|
|
V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
|
@@ -149,7 +190,7 @@ static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx,
|
|
|
|
cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic,
|
|
pic_order_cnt,
|
|
- buffer_index);
|
|
+ buffer_index, sps);
|
|
}
|
|
}
|
|
|
|
@@ -386,36 +427,6 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
width_in_ctb_luma =
|
|
DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
|
|
|
|
- /* 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;
|
|
-
|
|
- /*
|
|
- * 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(ctx, CEDRUS_CODEC_H265);
|
|
|
|
@@ -669,7 +680,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
|
|
/* Write decoded picture buffer in pic list. */
|
|
cedrus_h265_frame_info_write_dpb(ctx, slice_params->dpb,
|
|
- slice_params->num_active_dpb_entries);
|
|
+ slice_params->num_active_dpb_entries, sps);
|
|
|
|
/* Output frame. */
|
|
|
|
@@ -680,7 +691,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
cedrus_h265_frame_info_write_single(ctx, output_pic_list_index,
|
|
slice_params->pic_struct != 0,
|
|
pic_order_cnt,
|
|
- run->dst->vb2_buf.index);
|
|
+ run->dst->vb2_buf.index, sps);
|
|
|
|
cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index);
|
|
|
|
@@ -729,9 +740,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,
|
|
@@ -757,14 +765,6 @@ 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);
|
|
@@ -780,6 +780,16 @@ static void cedrus_h265_trigger(struct cedrus_ctx *ctx)
|
|
cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE);
|
|
}
|
|
|
|
+static void cedrus_h265_buf_cleanup(struct cedrus_ctx *ctx,
|
|
+ struct cedrus_buffer *buf)
|
|
+{
|
|
+ if (buf->codec.h265.mv_col_buf_size)
|
|
+ dma_free_coherent(ctx->dev->dev,
|
|
+ buf->codec.h265.mv_col_buf_size,
|
|
+ buf->codec.h265.mv_col_buf,
|
|
+ buf->codec.h265.mv_col_buf_dma);
|
|
+}
|
|
+
|
|
struct cedrus_dec_ops cedrus_dec_ops_h265 = {
|
|
.irq_clear = cedrus_h265_irq_clear,
|
|
.irq_disable = cedrus_h265_irq_disable,
|
|
@@ -788,4 +798,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h265 = {
|
|
.start = cedrus_h265_start,
|
|
.stop = cedrus_h265_stop,
|
|
.trigger = cedrus_h265_trigger,
|
|
+ .buf_cleanup = cedrus_h265_buf_cleanup,
|
|
};
|
|
--
|
|
2.24.0
|
|
|
|
|
|
From b38b517739880462a43a1f4b36cf9384ffdae66c Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
Date: Sat, 9 Nov 2019 14:12:42 +0100
|
|
Subject: [PATCH 14/14] media: cedrus: h264: Improve buffer management
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
|
---
|
|
drivers/staging/media/sunxi/cedrus/cedrus.h | 3 +
|
|
.../staging/media/sunxi/cedrus/cedrus_h264.c | 93 ++++++++-----------
|
|
2 files changed, 44 insertions(+), 52 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
index d8a4f8e83f94..f8264953dd04 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
|
|
@@ -94,6 +94,9 @@ struct cedrus_buffer {
|
|
struct {
|
|
unsigned int position;
|
|
enum cedrus_h264_pic_type pic_type;
|
|
+ void *mv_col_buf;
|
|
+ dma_addr_t mv_col_buf_dma;
|
|
+ ssize_t mv_col_buf_size;
|
|
} h264;
|
|
struct {
|
|
void *mv_col_buf;
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
|
|
index b0ee4aed79f9..aa5bd181cdaf 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;
|
|
+ dma_addr_t addr = buf->codec.h264.mv_col_buf_dma;
|
|
|
|
- /* Adjust for the position */
|
|
- addr += position * ctx->codec.h264.mv_col_buf_field_size * 2;
|
|
-
|
|
- /* Adjust for the field */
|
|
- addr += field * ctx->codec.h264.mv_col_buf_field_size;
|
|
+ /* Adjust for the field */
|
|
+ if (field)
|
|
+ addr += buf->codec.h264.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,
|
|
@@ -147,6 +144,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->codec.h264.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->codec.h264.mv_col_buf_size = field_size * 2;
|
|
+ output_buf->codec.h264.mv_col_buf =
|
|
+ dma_alloc_coherent(dev->dev,
|
|
+ output_buf->codec.h264.mv_col_buf_size,
|
|
+ &output_buf->codec.h264.mv_col_buf_dma,
|
|
+ GFP_KERNEL);
|
|
+
|
|
+ if (!output_buf->codec.h264.mv_col_buf)
|
|
+ output_buf->codec.h264.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)
|
|
@@ -525,8 +544,6 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx)
|
|
{
|
|
struct cedrus_dev *dev = ctx->dev;
|
|
unsigned int pic_info_size;
|
|
- unsigned int field_size;
|
|
- unsigned int mv_col_size;
|
|
int ret;
|
|
|
|
/* Formula for picture buffer size is taken from CedarX source. */
|
|
@@ -569,37 +586,6 @@ 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;
|
|
-
|
|
- /*
|
|
- * 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;
|
|
- }
|
|
-
|
|
if (ctx->src_fmt.width > 2048) {
|
|
/*
|
|
* Formulas for deblock and intra prediction buffer sizes
|
|
@@ -615,7 +601,7 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx)
|
|
GFP_KERNEL);
|
|
if (!ctx->codec.h264.deblk_buf) {
|
|
ret = -ENOMEM;
|
|
- goto err_mv_col_buf;
|
|
+ goto err_neighbor_buf;
|
|
}
|
|
|
|
ctx->codec.h264.intra_pred_buf_size =
|
|
@@ -638,11 +624,6 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx)
|
|
ctx->codec.h264.deblk_buf,
|
|
ctx->codec.h264.deblk_buf_dma);
|
|
|
|
-err_mv_col_buf:
|
|
- 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);
|
|
-
|
|
err_neighbor_buf:
|
|
dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE,
|
|
ctx->codec.h264.neighbor_info_buf,
|
|
@@ -659,9 +640,6 @@ 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);
|
|
@@ -686,6 +664,16 @@ static void cedrus_h264_trigger(struct cedrus_ctx *ctx)
|
|
VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE);
|
|
}
|
|
|
|
+static void cedrus_h264_buf_cleanup(struct cedrus_ctx *ctx,
|
|
+ struct cedrus_buffer *buf)
|
|
+{
|
|
+ if (buf->codec.h264.mv_col_buf_size)
|
|
+ dma_free_coherent(ctx->dev->dev,
|
|
+ buf->codec.h264.mv_col_buf_size,
|
|
+ buf->codec.h264.mv_col_buf,
|
|
+ buf->codec.h264.mv_col_buf_dma);
|
|
+}
|
|
+
|
|
struct cedrus_dec_ops cedrus_dec_ops_h264 = {
|
|
.irq_clear = cedrus_h264_irq_clear,
|
|
.irq_disable = cedrus_h264_irq_disable,
|
|
@@ -694,4 +682,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h264 = {
|
|
.start = cedrus_h264_start,
|
|
.stop = cedrus_h264_stop,
|
|
.trigger = cedrus_h264_trigger,
|
|
+ .buf_cleanup = cedrus_h264_buf_cleanup,
|
|
};
|
|
--
|
|
2.24.0
|