Merge pull request #3972 from jernejsk/cedrus_update

Allwinner: Rework HW decoding
This commit is contained in:
CvH 2019-11-13 08:27:13 +01:00 committed by GitHub
commit d6c13231e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 7418 additions and 3590 deletions

View File

@ -1,7 +1,7 @@
From e6cec3f54693e7e2c10b6b7bc8f72daa6e9a77dc Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 3 Dec 2018 23:48:04 +0100
Subject: [PATCH] avutil: add av_buffer_pool_flush()
Subject: [PATCH 01/12] avutil: add av_buffer_pool_flush()
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
@ -49,3 +49,6 @@ index 73b6bd0b14..0678fa4bea 100644
/**
* Mark the pool as being available for freeing. It will actually be freed only
* once all the allocated buffers associated with the pool are released. Thus it
--
2.24.0

View File

@ -1,16 +1,16 @@
From b810081f898fc4faec35519c6e7e9d275bf2bbcf Mon Sep 17 00:00:00 2001
From 457a74f059e5467f7f24f15be1b0e87a34e8cabc Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sat, 15 Dec 2018 22:32:16 +0100
Subject: [PATCH] Add common V4L2 request API code
Subject: [PATCH 02/12] Add common V4L2 request API code
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
configure | 12 +
libavcodec/Makefile | 1 +
libavcodec/hwaccel.h | 2 +
libavcodec/v4l2_request.c | 919 ++++++++++++++++++++++++++++++++++++++
libavcodec/v4l2_request.h | 69 +++
5 files changed, 1003 insertions(+)
libavcodec/v4l2_request.c | 943 ++++++++++++++++++++++++++++++++++++++
libavcodec/v4l2_request.h | 72 +++
5 files changed, 1030 insertions(+)
create mode 100644 libavcodec/v4l2_request.c
create mode 100644 libavcodec/v4l2_request.h
@ -112,10 +112,10 @@ index 3aaa92571c..2eefc91e7e 100644
#endif /* AVCODEC_HWACCEL_H */
diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
new file mode 100644
index 0000000000..bf9d049eff
index 0000000000..1dabf77689
--- /dev/null
+++ b/libavcodec/v4l2_request.c
@@ -0,0 +1,919 @@
@@ -0,0 +1,943 @@
+/*
+ * This file is part of FFmpeg.
+ *
@ -216,7 +216,7 @@ index 0000000000..bf9d049eff
+ return control.default_value;
+}
+
+static int v4l2_request_queue_buffer(V4L2RequestContext *ctx, int request_fd, V4L2RequestBuffer *buf)
+static int v4l2_request_queue_buffer(V4L2RequestContext *ctx, int request_fd, V4L2RequestBuffer *buf, uint32_t flags)
+{
+ struct v4l2_plane planes[1] = {};
+ struct v4l2_buffer buffer = {
@ -226,7 +226,7 @@ index 0000000000..bf9d049eff
+ .timestamp.tv_usec = buf->index + 1,
+ .bytesused = buf->used,
+ .request_fd = request_fd,
+ .flags = (request_fd >= 0) ? V4L2_BUF_FLAG_REQUEST_FD : 0,
+ .flags = ((request_fd >= 0) ? V4L2_BUF_FLAG_REQUEST_FD : 0) | flags,
+ };
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) {
@ -308,7 +308,7 @@ index 0000000000..bf9d049eff
+ return 0;
+}
+
+int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count)
+static int v4l2_request_queue_decode(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice)
+{
+ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0];
@ -316,7 +316,7 @@ index 0000000000..bf9d049eff
+ fd_set except_fds;
+ int ret;
+
+ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p used=%u controls=%d index=%d fd=%d request_fd=%d\n", __func__, avctx, req->output.used, count, req->capture.index, req->capture.fd, req->request_fd);
+ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p used=%u controls=%d index=%d fd=%d request_fd=%d first_slice=%d last_slice=%d\n", __func__, avctx, req->output.used, count, req->capture.index, req->capture.fd, req->request_fd, first_slice, last_slice);
+
+ ret = v4l2_request_set_controls(ctx, req->request_fd, control, count);
+ if (ret < 0) {
@ -326,16 +326,18 @@ index 0000000000..bf9d049eff
+
+ memset(req->output.addr + req->output.used, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+
+ ret = v4l2_request_queue_buffer(ctx, req->request_fd, &req->output);
+ ret = v4l2_request_queue_buffer(ctx, req->request_fd, &req->output, last_slice ? 0 : V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "%s: queue output buffer %d failed for request %d, %s (%d)\n", __func__, req->output.index, req->request_fd, strerror(errno), errno);
+ return -1;
+ }
+
+ ret = v4l2_request_queue_buffer(ctx, -1, &req->capture);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "%s: queue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno);
+ return -1;
+ if (first_slice) {
+ ret = v4l2_request_queue_buffer(ctx, -1, &req->capture, 0);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "%s: queue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno);
+ return -1;
+ }
+ }
+
+ // NOTE: do we need to dequeue when request fails/timeout?
@ -365,10 +367,12 @@ index 0000000000..bf9d049eff
+ return -1;
+ }
+
+ ret = v4l2_request_dequeue_buffer(ctx, &req->capture);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "%s: dequeue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno);
+ return -1;
+ if (last_slice) {
+ ret = v4l2_request_dequeue_buffer(ctx, &req->capture);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "%s: dequeue capture buffer %d failed for request %d, %s (%d)\n", __func__, req->capture.index, req->request_fd, strerror(errno), errno);
+ return -1;
+ }
+ }
+
+ // TODO: check errors
@ -380,7 +384,10 @@ index 0000000000..bf9d049eff
+ return -1;
+ }
+
+ return v4l2_request_set_drm_descriptor(req, &ctx->format);
+ if (last_slice)
+ return v4l2_request_set_drm_descriptor(req, &ctx->format);
+
+ return 0;
+
+fail:
+ ret = v4l2_request_dequeue_buffer(ctx, &req->output);
@ -398,6 +405,22 @@ index 0000000000..bf9d049eff
+ return -1;
+}
+
+int ff_v4l2_request_decode_slice(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice)
+{
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0];
+
+ // fall back to queue each slice as a full frame
+ if ((req->output.capabilities & V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF) != V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF)
+ return v4l2_request_queue_decode(avctx, frame, control, count, 1, 1);
+
+ return v4l2_request_queue_decode(avctx, frame, control, count, first_slice, last_slice);
+}
+
+int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count)
+{
+ return v4l2_request_queue_decode(avctx, frame, control, count, 1, 1);
+}
+
+static int v4l2_request_try_format(AVCodecContext *avctx, enum v4l2_buf_type type, uint32_t pixelformat)
+{
+ V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data;
@ -866,6 +889,7 @@ index 0000000000..bf9d049eff
+ }
+
+ buf->index = buffers.index;
+ buf->capabilities = buffers.capabilities;
+ buf->used = 0;
+
+ buf->buffer.type = type;
@ -1037,10 +1061,10 @@ index 0000000000..bf9d049eff
+}
diff --git a/libavcodec/v4l2_request.h b/libavcodec/v4l2_request.h
new file mode 100644
index 0000000000..1f45772d8b
index 0000000000..d4146bd4ee
--- /dev/null
+++ b/libavcodec/v4l2_request.h
@@ -0,0 +1,69 @@
@@ -0,0 +1,72 @@
+/*
+ * This file is part of FFmpeg.
+ *
@ -1081,6 +1105,7 @@ index 0000000000..1f45772d8b
+ uint32_t height;
+ uint32_t size;
+ uint32_t used;
+ uint32_t capabilities;
+ struct v4l2_buffer buffer;
+} V4L2RequestBuffer;
+
@ -1101,6 +1126,8 @@ index 0000000000..1f45772d8b
+
+int ff_v4l2_request_query_control_default_value(AVCodecContext *avctx, uint32_t id);
+
+int ff_v4l2_request_decode_slice(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count, int first_slice, int last_slice);
+
+int ff_v4l2_request_decode_frame(AVCodecContext *avctx, AVFrame *frame, struct v4l2_ext_control *control, int count);
+
+int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t buffersize, struct v4l2_ext_control *control, int count);
@ -1110,3 +1137,6 @@ index 0000000000..1f45772d8b
+int ff_v4l2_request_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx);
+
+#endif /* AVCODEC_V4L2_REQUEST_H */
--
2.24.0

View File

@ -1,7 +1,7 @@
From f31319e29405004b84f17e30602f77dae671b53e Mon Sep 17 00:00:00 2001
From d46c4def125a142419db249051fbaa8e743e3e53 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sat, 15 Dec 2018 22:32:16 +0100
Subject: [PATCH] Add V4L2 request API mpeg2 hwaccel
Subject: [PATCH 03/12] Add V4L2 request API mpeg2 hwaccel
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
@ -242,3 +242,6 @@ index 0000000000..782b9c2471
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};
--
2.24.0

View File

@ -1,7 +1,7 @@
From 389f6557715439d5fa974f0cc55e1fa68735ec61 Mon Sep 17 00:00:00 2001
From fb59440a268d956bffa40604e4422420453b4605 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 15 Dec 2018 22:32:16 +0100
Subject: [PATCH] Add V4L2 request API h264 hwaccel
Subject: [PATCH 04/12] Add V4L2 request API h264 hwaccel
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
@ -11,8 +11,8 @@ Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
libavcodec/h264_slice.c | 4 +
libavcodec/h264dec.c | 3 +
libavcodec/hwaccels.h | 1 +
libavcodec/v4l2_request_h264.c | 420 +++++++++++++++++++++++++++++++++
6 files changed, 432 insertions(+)
libavcodec/v4l2_request_h264.c | 443 +++++++++++++++++++++++++++++++++
6 files changed, 455 insertions(+)
create mode 100644 libavcodec/v4l2_request_h264.c
diff --git a/configure b/configure
@ -98,10 +98,10 @@ index ef54de2a3b..003200edea 100644
extern const AVHWAccel ff_h264_videotoolbox_hwaccel;
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
new file mode 100644
index 0000000000..fb9913922d
index 0000000000..81b3c4b092
--- /dev/null
+++ b/libavcodec/v4l2_request_h264.c
@@ -0,0 +1,420 @@
@@ -0,0 +1,443 @@
+/*
+ * This file is part of FFmpeg.
+ *
@ -130,6 +130,7 @@ index 0000000000..fb9913922d
+ struct v4l2_ctrl_h264_scaling_matrix scaling_matrix;
+ struct v4l2_ctrl_h264_decode_params decode_params;
+ struct v4l2_ctrl_h264_slice_params slice_params[16];
+ int first_slice;
+} V4L2RequestControlsH264;
+
+typedef struct V4L2RequestContextH264 {
@ -297,13 +298,22 @@ index 0000000000..fb9913922d
+{
+ const H264Context *h = avctx->priv_data;
+ const PPS *pps = h->ps.pps;
+ const SPS *sps = h->ps.sps;
+ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private;
+
+ fill_sps(&controls->sps, h);
+ fill_pps(&controls->pps, h);
+
+ memcpy(controls->scaling_matrix.scaling_list_4x4, pps->scaling_matrix4, sizeof(controls->scaling_matrix.scaling_list_4x4));
+ memcpy(controls->scaling_matrix.scaling_list_8x8, pps->scaling_matrix8, sizeof(controls->scaling_matrix.scaling_list_8x8));
+ memcpy(controls->scaling_matrix.scaling_list_8x8[0], pps->scaling_matrix8[0], sizeof(controls->scaling_matrix.scaling_list_8x8[0]));
+ memcpy(controls->scaling_matrix.scaling_list_8x8[1], pps->scaling_matrix8[3], sizeof(controls->scaling_matrix.scaling_list_8x8[1]));
+
+ if (sps->chroma_format_idc == 3) {
+ memcpy(controls->scaling_matrix.scaling_list_8x8[2], pps->scaling_matrix8[1], sizeof(controls->scaling_matrix.scaling_list_8x8[2]));
+ memcpy(controls->scaling_matrix.scaling_list_8x8[3], pps->scaling_matrix8[4], sizeof(controls->scaling_matrix.scaling_list_8x8[3]));
+ memcpy(controls->scaling_matrix.scaling_list_8x8[4], pps->scaling_matrix8[2], sizeof(controls->scaling_matrix.scaling_list_8x8[4]));
+ memcpy(controls->scaling_matrix.scaling_list_8x8[5], pps->scaling_matrix8[5], sizeof(controls->scaling_matrix.scaling_list_8x8[5]));
+ }
+
+ controls->decode_params = (struct v4l2_ctrl_h264_decode_params) {
+ .num_slices = 0,
@ -317,13 +327,16 @@ index 0000000000..fb9913922d
+
+ fill_dpb(&controls->decode_params, h);
+
+ controls->first_slice = !FIELD_PICTURE(h) || h->first_field;
+
+ return ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f);
+}
+
+static int v4l2_request_h264_end_frame(AVCodecContext *avctx)
+static int v4l2_request_h264_queue_decode(AVCodecContext *avctx, int last_slice)
+{
+ const H264Context *h = avctx->priv_data;
+ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private;
+ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data;
+
+ struct v4l2_ext_control control[] = {
+ {
@ -353,6 +366,9 @@ index 0000000000..fb9913922d
+ },
+ };
+
+ if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED)
+ return ff_v4l2_request_decode_slice(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control), controls->first_slice, last_slice);
+
+ return ff_v4l2_request_decode_frame(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control));
+}
+
@ -367,12 +383,13 @@ index 0000000000..fb9913922d
+ int i, ret, count, slice = FFMIN(controls->decode_params.num_slices, 15);
+
+ if (ctx->decode_mode == V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED && slice) {
+ ret = v4l2_request_h264_end_frame(avctx);
+ ret = v4l2_request_h264_queue_decode(avctx, 0);
+ if (ret)
+ return ret;
+
+ ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f);
+ slice = controls->decode_params.num_slices = 0;
+ controls->first_slice = 0;
+ }
+
+ controls->slice_params[slice] = (struct v4l2_ctrl_h264_slice_params) {
@ -448,6 +465,12 @@ index 0000000000..fb9913922d
+ return 0;
+}
+
+static int v4l2_request_h264_end_frame(AVCodecContext *avctx)
+{
+ const H264Context *h = avctx->priv_data;
+ return v4l2_request_h264_queue_decode(avctx, !FIELD_PICTURE(h) || !h->first_field);
+}
+
+static int v4l2_request_h264_set_controls(AVCodecContext *avctx)
+{
+ V4L2RequestContextH264 *ctx = avctx->internal->hwaccel_priv_data;
@ -522,3 +545,6 @@ index 0000000000..fb9913922d
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};
--
2.24.0

View File

@ -1,7 +1,7 @@
From 0cd5948e34df8acdbc84efc7ce662eee03ce88e3 Mon Sep 17 00:00:00 2001
From 2511b50434e37a56af86bd38b76a6b5cf4d3117b Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 15 Dec 2018 22:32:16 +0100
Subject: [PATCH] Add V4L2 request API hevc hwaccel
Subject: [PATCH 05/12] Add V4L2 request API hevc hwaccel
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
@ -10,8 +10,8 @@ Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
libavcodec/Makefile | 1 +
libavcodec/hevcdec.c | 10 +
libavcodec/hwaccels.h | 1 +
libavcodec/v4l2_request_hevc.c | 391 +++++++++++++++++++++++++++++++++
5 files changed, 406 insertions(+)
libavcodec/v4l2_request_hevc.c | 527 +++++++++++++++++++++++++++++++++
5 files changed, 542 insertions(+)
create mode 100644 libavcodec/v4l2_request_hevc.c
diff --git a/configure b/configure
@ -103,10 +103,10 @@ index 003200edea..d183675abe 100644
extern const AVHWAccel ff_hevc_videotoolbox_hwaccel;
diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c
new file mode 100644
index 0000000000..38969d77fb
index 0000000000..da1fd666d7
--- /dev/null
+++ b/libavcodec/v4l2_request_hevc.c
@@ -0,0 +1,391 @@
@@ -0,0 +1,527 @@
+/*
+ * This file is part of FFmpeg.
+ *
@ -133,9 +133,17 @@ index 0000000000..38969d77fb
+ struct v4l2_ctrl_hevc_sps sps;
+ struct v4l2_ctrl_hevc_pps pps;
+ struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix;
+ struct v4l2_ctrl_hevc_slice_params slice_params;
+ struct v4l2_ctrl_hevc_slice_params slice_params[16];
+ int first_slice;
+ int num_slices; //TODO: this should be in control
+} V4L2RequestControlsHEVC;
+
+typedef struct V4L2RequestContextHEVC {
+ V4L2RequestContext base;
+ int decode_mode;
+ int start_code;
+} V4L2RequestContextHEVC;
+
+static void v4l2_request_hevc_fill_pred_table(const HEVCContext *h, struct v4l2_hevc_pred_weight_table *table)
+{
+ int32_t luma_weight_denom, chroma_weight_denom;
@ -233,6 +241,9 @@ index 0000000000..38969d77fb
+ .bit_size = 0,
+ .data_bit_offset = get_bits_count(&h->HEVClc->gb),
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ .slice_segment_addr = sh->slice_segment_addr,
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
+ .nal_unit_type = h->nal_unit_type,
+ .nuh_temporal_id_plus1 = h->temporal_id + 1,
@ -241,27 +252,18 @@ index 0000000000..38969d77fb
+ .slice_type = sh->slice_type,
+ .colour_plane_id = sh->colour_plane_id,
+ .slice_pic_order_cnt = pic->poc,
+ .slice_sao_luma_flag = sh->slice_sample_adaptive_offset_flag[0],
+ .slice_sao_chroma_flag = sh->slice_sample_adaptive_offset_flag[1],
+ .slice_temporal_mvp_enabled_flag = sh->slice_temporal_mvp_enabled_flag,
+ .num_ref_idx_l0_active_minus1 = sh->nb_refs[L0] ? sh->nb_refs[L0] - 1 : 0,
+ .num_ref_idx_l1_active_minus1 = sh->nb_refs[L1] ? sh->nb_refs[L1] - 1 : 0,
+ .mvd_l1_zero_flag = sh->mvd_l1_zero_flag,
+ .cabac_init_flag = sh->cabac_init_flag,
+ .collocated_from_l0_flag = sh->collocated_list == L0 ? 1 : 0,
+ .collocated_ref_idx = sh->slice_temporal_mvp_enabled_flag ? sh->collocated_ref_idx : 0,
+ .five_minus_max_num_merge_cand = sh->slice_type == HEVC_SLICE_I ? 0 : 5 - sh->max_num_merge_cand,
+ .use_integer_mv_flag = 0,
+ .slice_qp_delta = sh->slice_qp_delta,
+ .slice_cb_qp_offset = sh->slice_cb_qp_offset,
+ .slice_cr_qp_offset = sh->slice_cr_qp_offset,
+ .slice_act_y_qp_offset = 0,
+ .slice_act_cb_qp_offset = 0,
+ .slice_act_cr_qp_offset = 0,
+ .slice_deblocking_filter_disabled_flag = sh->disable_deblocking_filter_flag,
+ .slice_beta_offset_div2 = sh->beta_offset / 2,
+ .slice_tc_offset_div2 = sh->tc_offset / 2,
+ .slice_loop_filter_across_slices_enabled_flag = sh->slice_loop_filter_across_slices_enabled_flag,
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */
+ .pic_struct = h->sei.picture_timing.picture_struct,
@ -270,11 +272,32 @@ index 0000000000..38969d77fb
+ .num_rps_poc_st_curr_before = h->rps[ST_CURR_BEF].nb_refs,
+ .num_rps_poc_st_curr_after = h->rps[ST_CURR_AFT].nb_refs,
+ .num_rps_poc_lt_curr = h->rps[LT_CURR].nb_refs,
+
+ .slice_segment_addr = sh->slice_segment_addr,
+ .first_slice_segment_in_pic_flag = sh->first_slice_in_pic_flag,
+ };
+
+ if (sh->slice_sample_adaptive_offset_flag[0])
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA;
+
+ if (sh->slice_sample_adaptive_offset_flag[1])
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA;
+
+ if (sh->slice_temporal_mvp_enabled_flag)
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED;
+
+ if (sh->mvd_l1_zero_flag)
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO;
+
+ if (sh->cabac_init_flag)
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT;
+
+ if (sh->collocated_list == L0)
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0;
+
+ if (sh->disable_deblocking_filter_flag)
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED;
+
+ if (sh->slice_loop_filter_across_slices_enabled_flag)
+ slice_params->flags |= V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED;
+
+ for (i = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) {
+ const HEVCFrame *frame = &h->DPB[i];
+ if (frame != pic && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) {
@ -332,7 +355,6 @@ index 0000000000..38969d77fb
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */
+ controls->sps = (struct v4l2_ctrl_hevc_sps) {
+ .chroma_format_idc = sps->chroma_format_idc,
+ .separate_colour_plane_flag = sps->separate_colour_plane_flag,
+ .pic_width_in_luma_samples = sps->width,
+ .pic_height_in_luma_samples = sps->height,
+ .bit_depth_luma_minus8 = sps->bit_depth - 8,
@ -347,22 +369,41 @@ index 0000000000..38969d77fb
+ .log2_diff_max_min_luma_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size,
+ .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
+ .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
+ .scaling_list_enabled_flag = sps->scaling_list_enable_flag,
+ .amp_enabled_flag = sps->amp_enabled_flag,
+ .sample_adaptive_offset_enabled_flag = sps->sao_enabled,
+ .pcm_enabled_flag = sps->pcm_enabled_flag,
+ .pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1,
+ .pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1,
+ .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3,
+ .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size,
+ .pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag,
+ .num_short_term_ref_pic_sets = sps->nb_st_rps,
+ .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag,
+ .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps,
+ .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag,
+ .strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag,
+ };
+
+ if (sps->separate_colour_plane_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE;
+
+ if (sps->scaling_list_enable_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED;
+
+ if (sps->amp_enabled_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_AMP_ENABLED;
+
+ if (sps->sao_enabled)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET;
+
+ if (sps->pcm_enabled_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_PCM_ENABLED;
+
+ if (sps->pcm.loop_filter_disable_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED;
+
+ if (sps->long_term_ref_pics_present_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT;
+
+ if (sps->sps_temporal_mvp_enabled_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED;
+
+ if (sps->sps_strong_intra_smoothing_enable_flag)
+ controls->sps.flags |= V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED;
+
+ if (sl) {
+ for (int i = 0; i < 6; i++) {
+ for (int j = 0; j < 16; j++)
@ -381,41 +422,79 @@ index 0000000000..38969d77fb
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */
+ controls->pps = (struct v4l2_ctrl_hevc_pps) {
+ .dependent_slice_segment_flag = pps->dependent_slice_segments_enabled_flag,
+ .output_flag_present_flag = pps->output_flag_present_flag,
+ .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
+ .sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag,
+ .cabac_init_present_flag = pps->cabac_init_present_flag,
+ .init_qp_minus26 = pps->pic_init_qp_minus26,
+ .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
+ .transform_skip_enabled_flag = pps->transform_skip_enabled_flag,
+ .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag,
+ .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
+ .pps_cb_qp_offset = pps->cb_qp_offset,
+ .pps_cr_qp_offset = pps->cr_qp_offset,
+ .pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag,
+ .weighted_pred_flag = pps->weighted_pred_flag,
+ .weighted_bipred_flag = pps->weighted_bipred_flag,
+ .transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag,
+ .tiles_enabled_flag = pps->tiles_enabled_flag,
+ .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag,
+ .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag,
+ .pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag,
+ .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag,
+ .pps_disable_deblocking_filter_flag = pps->disable_dbf,
+ .pps_beta_offset_div2 = pps->beta_offset / 2,
+ .pps_tc_offset_div2 = pps->tc_offset / 2,
+ .lists_modification_present_flag = pps->lists_modification_present_flag,
+ .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2,
+ .slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag,
+ .scaling_list_enable_flag = pps->scaling_list_data_present_flag, // pps_scaling_list_data_present_flag
+ };
+
+ if (pps->dependent_slice_segments_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT;
+
+ if (pps->output_flag_present_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT;
+
+ if (pps->sign_data_hiding_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED;
+
+ if (pps->cabac_init_present_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT;
+
+ if (pps->constrained_intra_pred_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED;
+
+ if (pps->transform_skip_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED;
+
+ if (pps->cu_qp_delta_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED;
+
+ if (pps->pic_slice_level_chroma_qp_offsets_present_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT;
+
+ if (pps->weighted_pred_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED;
+
+ if (pps->weighted_bipred_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED;
+
+ if (pps->transquant_bypass_enable_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED;
+
+ if (pps->tiles_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_TILES_ENABLED;
+
+ if (pps->entropy_coding_sync_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED;
+
+ if (pps->loop_filter_across_tiles_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED;
+
+ if (pps->seq_loop_filter_across_slices_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED;
+
+ if (pps->deblocking_filter_override_enabled_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED;
+
+ if (pps->disable_dbf)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER;
+
+ if (pps->lists_modification_present_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT;
+
+ if (pps->slice_header_extension_present_flag)
+ controls->pps.flags |= V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT;
+
+ if (pps->tiles_enabled_flag) {
+ controls->pps.num_tile_columns_minus1 = pps->num_tile_columns - 1;
+ controls->pps.num_tile_rows_minus1 = pps->num_tile_rows - 1;
+
+ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p tiles_enabled_flag=%d num_tile_columns=%d num_tile_rows=%d\n", __func__, avctx, pps->tiles_enabled_flag, pps->num_tile_columns, pps->num_tile_rows);
+ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p tiles_enabled_flag=%d num_tile_columns=%d num_tile_rows=%d\n",
+ __func__, avctx, pps->tiles_enabled_flag, pps->num_tile_columns, pps->num_tile_rows);
+
+ for (int i = 0; i < pps->num_tile_columns; i++)
+ controls->pps.column_width_minus1[i] = pps->column_width[i] - 1;
@ -424,14 +503,17 @@ index 0000000000..38969d77fb
+ controls->pps.row_height_minus1[i] = pps->row_height[i] - 1;
+ }
+
+ controls->first_slice = 1;
+ controls->num_slices = 0;
+
+ return ff_v4l2_request_reset_frame(avctx, h->ref->frame);
+}
+
+static int v4l2_request_hevc_end_frame(AVCodecContext *avctx)
+static int v4l2_request_hevc_queue_decode(AVCodecContext *avctx, int last_slice)
+{
+ const HEVCContext *h = avctx->priv_data;
+ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->ref->frame->data[0];
+ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data;
+
+ struct v4l2_ext_control control[] = {
+ {
@ -452,35 +534,89 @@ index 0000000000..38969d77fb
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS,
+ .ptr = &controls->slice_params,
+ .size = sizeof(controls->slice_params),
+ .size = sizeof(controls->slice_params[0]) * FFMIN(controls->num_slices, 16),
+ },
+ };
+
+ controls->slice_params.bit_size = req->output.used * 8;
+ if (ctx->decode_mode == V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED)
+ return ff_v4l2_request_decode_slice(avctx, h->ref->frame, control, FF_ARRAY_ELEMS(control), controls->first_slice, last_slice);
+
+ return ff_v4l2_request_decode_frame(avctx, h->ref->frame, control, FF_ARRAY_ELEMS(control));
+}
+
+static int v4l2_request_hevc_end_frame(AVCodecContext *avctx)
+{
+ return v4l2_request_hevc_queue_decode(avctx, 1);
+}
+
+static int v4l2_request_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
+{
+ const HEVCContext *h = avctx->priv_data;
+ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->ref->frame->data[0];
+ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data;
+ int ret, slice = FFMIN(controls->num_slices, 15);
+
+ // HACK: trigger decode per slice
+ if (req->output.used) {
+ v4l2_request_hevc_end_frame(avctx);
+ ff_v4l2_request_reset_frame(avctx, h->ref->frame);
+ if (ctx->decode_mode == V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED && slice) {
+ ret = v4l2_request_hevc_queue_decode(avctx, 0);
+ if (ret)
+ return ret;
+
+ ff_v4l2_request_reset_frame(avctx, h->ref->frame);
+ slice = controls->num_slices = 0;
+ controls->first_slice = 0;
+ }
+
+ v4l2_request_hevc_fill_slice_params(h, &controls->slice_params);
+ v4l2_request_hevc_fill_slice_params(h, &controls->slice_params[slice]);
+
+ return ff_v4l2_request_append_output_buffer(avctx, h->ref->frame, buffer, size);
+ ret = ff_v4l2_request_append_output_buffer(avctx, h->ref->frame, buffer, size);
+ if (ret)
+ return ret;
+
+ controls->slice_params[slice].bit_size = req->output.used * 8; //FIXME
+ controls->num_slices++;
+
+ return 0;
+}
+
+static int v4l2_request_hevc_set_controls(AVCodecContext *avctx)
+{
+ V4L2RequestContextHEVC *ctx = avctx->internal->hwaccel_priv_data;
+
+ struct v4l2_ext_control control[] = {
+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE, },
+ { .id = V4L2_CID_MPEG_VIDEO_HEVC_START_CODE, },
+ };
+
+ ctx->decode_mode = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE);
+ if (ctx->decode_mode != V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED &&
+ ctx->decode_mode != V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED) {
+ av_log(avctx, AV_LOG_ERROR, "%s: unsupported decode mode, %d\n", __func__, ctx->decode_mode);
+ return AVERROR(EINVAL);
+ }
+
+ ctx->start_code = ff_v4l2_request_query_control_default_value(avctx, V4L2_CID_MPEG_VIDEO_HEVC_START_CODE);
+ if (ctx->start_code != V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE &&
+ ctx->start_code != V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B) {
+ av_log(avctx, AV_LOG_ERROR, "%s: unsupported start code, %d\n", __func__, ctx->start_code);
+ return AVERROR(EINVAL);
+ }
+
+ control[0].value = ctx->decode_mode;
+ control[1].value = ctx->start_code;
+
+ return ff_v4l2_request_set_controls(avctx, control, FF_ARRAY_ELEMS(control));
+}
+
+static int v4l2_request_hevc_init(AVCodecContext *avctx)
+{
+ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_HEVC_SLICE, 3 * 1024 * 1024, NULL, 0);
+ int ret;
+
+ ret = ff_v4l2_request_init(avctx, V4L2_PIX_FMT_HEVC_SLICE, 3 * 1024 * 1024, NULL, 0);
+ if (ret)
+ return ret;
+
+ return v4l2_request_hevc_set_controls(avctx);
+}
+
+const AVHWAccel ff_hevc_v4l2request_hwaccel = {
@ -494,7 +630,10 @@ index 0000000000..38969d77fb
+ .frame_priv_data_size = sizeof(V4L2RequestControlsHEVC),
+ .init = v4l2_request_hevc_init,
+ .uninit = ff_v4l2_request_uninit,
+ .priv_data_size = sizeof(V4L2RequestContext),
+ .priv_data_size = sizeof(V4L2RequestContextHEVC),
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};
--
2.24.0

View File

@ -1,7 +1,7 @@
From 2537bdd10973c0fc3f757cab01fd71dd0ef6b1e1 Mon Sep 17 00:00:00 2001
From 13e487a5da1f64901391b99aa094a697fd2889aa Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@collabora.com>
Date: Wed, 22 May 2019 14:46:58 +0200
Subject: [PATCH] Add V4L2 request API vp8 hwaccel
Subject: [PATCH 06/12] Add V4L2 request API vp8 hwaccel
Need to fix the STREAMOFF/STREAMON issue in a proper way.
@ -280,3 +280,6 @@ index 62b9f8bc2d..55966b9d56 100644
#endif
NULL
},
--
2.24.0

View File

@ -1,20 +1,21 @@
From be39d2e3e5228cdc2cf355d85f5566205f6cb65d Mon Sep 17 00:00:00 2001
From 23e7417b7ceb66f2ff4a98da5b1785d24994f865 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Thu, 14 Feb 2019 23:20:05 +0100
Subject: [PATCH] Add and use private linux headers for V4L2 request API ctrls
Subject: [PATCH 07/12] Add and use private linux headers for V4L2 request API
ctrls
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
configure | 6 +-
libavcodec/h264-ctrls.h | 210 ++++++++++++++++++++++++++++++++
libavcodec/hevc-ctrls.h | 203 ++++++++++++++++++++++++++++++
libavcodec/mpeg2-ctrls.h | 82 +++++++++++++
libavcodec/h264-ctrls.h | 210 +++++++++++++++++++++++++++++
libavcodec/hevc-ctrls.h | 229 ++++++++++++++++++++++++++++++++
libavcodec/mpeg2-ctrls.h | 82 ++++++++++++
libavcodec/v4l2_request_h264.c | 1 +
libavcodec/v4l2_request_hevc.c | 1 +
libavcodec/v4l2_request_mpeg2.c | 1 +
libavcodec/v4l2_request_vp8.c | 1 +
libavcodec/vp8-ctrls.h | 112 +++++++++++++++++
9 files changed, 614 insertions(+), 3 deletions(-)
libavcodec/vp8-ctrls.h | 112 ++++++++++++++++
9 files changed, 640 insertions(+), 3 deletions(-)
create mode 100644 libavcodec/h264-ctrls.h
create mode 100644 libavcodec/hevc-ctrls.h
create mode 100644 libavcodec/mpeg2-ctrls.h
@ -269,10 +270,10 @@ index 0000000000..e877bf1d53
+#endif
diff --git a/libavcodec/hevc-ctrls.h b/libavcodec/hevc-ctrls.h
new file mode 100644
index 0000000000..eee4479c7a
index 0000000000..d1b094c8aa
--- /dev/null
+++ b/libavcodec/hevc-ctrls.h
@@ -0,0 +1,203 @@
@@ -0,0 +1,229 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * These are the HEVC state controls for use with stateless HEVC
@ -295,6 +296,8 @@ index 0000000000..eee4479c7a
+#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)
+
+/* enum v4l2_ctrl_type type values */
+#define V4L2_CTRL_TYPE_HEVC_SPS 0x0120
@ -302,15 +305,33 @@ index 0000000000..eee4479c7a
+#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,
+ V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_FRAME_BASED,
+};
+
+enum v4l2_mpeg_video_hevc_start_code {
+ V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE,
+ V4L2_MPEG_VIDEO_HEVC_START_CODE_ANNEX_B,
+};
+
+#define V4L2_HEVC_SLICE_TYPE_B 0
+#define V4L2_HEVC_SLICE_TYPE_P 1
+#define V4L2_HEVC_SLICE_TYPE_I 2
+
+#define V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE (1ULL << 0)
+#define V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED (1ULL << 1)
+#define V4L2_HEVC_SPS_FLAG_AMP_ENABLED (1ULL << 2)
+#define V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET (1ULL << 3)
+#define V4L2_HEVC_SPS_FLAG_PCM_ENABLED (1ULL << 4)
+#define V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED (1ULL << 5)
+#define V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT (1ULL << 6)
+#define V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED (1ULL << 7)
+#define V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED (1ULL << 8)
+
+/* The controls are not stable at the moment and will likely be reworked. */
+struct v4l2_ctrl_hevc_sps {
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */
+ __u8 chroma_format_idc;
+ __u8 separate_colour_plane_flag;
+ __u16 pic_width_in_luma_samples;
+ __u16 pic_height_in_luma_samples;
+ __u8 bit_depth_luma_minus8;
@ -325,56 +346,56 @@ index 0000000000..eee4479c7a
+ __u8 log2_diff_max_min_luma_transform_block_size;
+ __u8 max_transform_hierarchy_depth_inter;
+ __u8 max_transform_hierarchy_depth_intra;
+ __u8 scaling_list_enabled_flag;
+ __u8 amp_enabled_flag;
+ __u8 sample_adaptive_offset_enabled_flag;
+ __u8 pcm_enabled_flag;
+ __u8 pcm_sample_bit_depth_luma_minus1;
+ __u8 pcm_sample_bit_depth_chroma_minus1;
+ __u8 log2_min_pcm_luma_coding_block_size_minus3;
+ __u8 log2_diff_max_min_pcm_luma_coding_block_size;
+ __u8 pcm_loop_filter_disabled_flag;
+ __u8 num_short_term_ref_pic_sets;
+ __u8 long_term_ref_pics_present_flag;
+ __u8 num_long_term_ref_pics_sps;
+ __u8 sps_temporal_mvp_enabled_flag;
+ __u8 strong_intra_smoothing_enabled_flag;
+ __u8 chroma_format_idc;
+
+ __u8 padding;
+
+ __u64 flags;
+};
+
+#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 0)
+#define V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT (1ULL << 1)
+#define V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED (1ULL << 2)
+#define V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT (1ULL << 3)
+#define V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED (1ULL << 4)
+#define V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED (1ULL << 5)
+#define V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED (1ULL << 6)
+#define V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT (1ULL << 7)
+#define V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED (1ULL << 8)
+#define V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED (1ULL << 9)
+#define V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED (1ULL << 10)
+#define V4L2_HEVC_PPS_FLAG_TILES_ENABLED (1ULL << 11)
+#define V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED (1ULL << 12)
+#define V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED (1ULL << 13)
+#define V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 14)
+#define V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED (1ULL << 15)
+#define V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER (1ULL << 16)
+#define V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT (1ULL << 17)
+#define V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT (1ULL << 18)
+
+struct v4l2_ctrl_hevc_pps {
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */
+ __u8 dependent_slice_segment_flag;
+ __u8 output_flag_present_flag;
+ __u8 num_extra_slice_header_bits;
+ __u8 sign_data_hiding_enabled_flag;
+ __u8 cabac_init_present_flag;
+ __s8 init_qp_minus26;
+ __u8 constrained_intra_pred_flag;
+ __u8 transform_skip_enabled_flag;
+ __u8 cu_qp_delta_enabled_flag;
+ __u8 diff_cu_qp_delta_depth;
+ __s8 pps_cb_qp_offset;
+ __s8 pps_cr_qp_offset;
+ __u8 pps_slice_chroma_qp_offsets_present_flag;
+ __u8 weighted_pred_flag;
+ __u8 weighted_bipred_flag;
+ __u8 transquant_bypass_enabled_flag;
+ __u8 tiles_enabled_flag;
+ __u8 entropy_coding_sync_enabled_flag;
+ __u8 num_tile_columns_minus1;
+ __u8 num_tile_rows_minus1;
+ __u8 column_width_minus1[20];
+ __u8 row_height_minus1[22];
+ __u8 loop_filter_across_tiles_enabled_flag;
+ __u8 pps_loop_filter_across_slices_enabled_flag;
+ __u8 deblocking_filter_override_enabled_flag;
+ __u8 pps_disable_deblocking_filter_flag;
+ __s8 pps_beta_offset_div2;
+ __s8 pps_tc_offset_div2;
+ __u8 lists_modification_present_flag;
+ __u8 log2_parallel_merge_level_minus2;
+ __u8 slice_segment_header_extension_present_flag;
+ __u8 scaling_list_enable_flag;
+
+ __u8 padding[4];
+ __u64 flags;
+};
+
+#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE 0x01
@ -392,9 +413,6 @@ index 0000000000..eee4479c7a
+};
+
+struct v4l2_hevc_pred_weight_table {
+ __u8 luma_log2_weight_denom;
+ __s8 delta_chroma_log2_weight_denom;
+
+ __s8 delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __s8 luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __s8 delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
@ -405,13 +423,30 @@ index 0000000000..eee4479c7a
+ __s8 delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
+ __s8 chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
+
+ __u8 padding[2];
+ __u8 padding[6];
+
+ __u8 luma_log2_weight_denom;
+ __s8 delta_chroma_log2_weight_denom;
+};
+
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA (1ULL << 0)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA (1ULL << 1)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED (1ULL << 2)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO (1ULL << 3)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT (1ULL << 4)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0 (1ULL << 5)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV (1ULL << 6)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED (1ULL << 7)
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 8)
+
+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;
+ __u32 num_entry_point_offsets;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
+ __u8 nal_unit_type;
+ __u8 nuh_temporal_id_plus1;
@ -420,33 +455,23 @@ index 0000000000..eee4479c7a
+ __u8 slice_type;
+ __u8 colour_plane_id;
+ __u16 slice_pic_order_cnt;
+ __u8 slice_sao_luma_flag;
+ __u8 slice_sao_chroma_flag;
+ __u8 slice_temporal_mvp_enabled_flag;
+ __u8 num_ref_idx_l0_active_minus1;
+ __u8 num_ref_idx_l1_active_minus1;
+ __u8 mvd_l1_zero_flag;
+ __u8 cabac_init_flag;
+ __u8 collocated_from_l0_flag;
+ __u8 collocated_ref_idx;
+ __u8 five_minus_max_num_merge_cand;
+ __u8 use_integer_mv_flag;
+ __s8 slice_qp_delta;
+ __s8 slice_cb_qp_offset;
+ __s8 slice_cr_qp_offset;
+ __s8 slice_act_y_qp_offset;
+ __s8 slice_act_cb_qp_offset;
+ __s8 slice_act_cr_qp_offset;
+ __u8 slice_deblocking_filter_disabled_flag;
+ __s8 slice_beta_offset_div2;
+ __s8 slice_tc_offset_div2;
+ __u8 slice_loop_filter_across_slices_enabled_flag;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */
+ __u8 pic_struct;
+
+ /* 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];
+ __u8 num_active_dpb_entries;
+ __u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
@ -455,15 +480,17 @@ index 0000000000..eee4479c7a
+ __u8 num_rps_poc_st_curr_after;
+ __u8 num_rps_poc_lt_curr;
+
+ __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];
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */
+ struct v4l2_hevc_pred_weight_table pred_weight_table;
+
+ __u32 slice_segment_addr;
+ __u32 num_entry_point_offsets;
+ __u32 entry_point_offset_minus1[256];
+ __u8 first_slice_segment_in_pic_flag;
+
+ __u8 padding;
+ __u64 flags;
+};
+
+struct v4l2_ctrl_hevc_scaling_matrix {
@ -565,7 +592,7 @@ index 0000000000..6601455b3d
+
+#endif
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
index fb9913922d..b826c9d356 100644
index 81b3c4b092..ca306b6a3f 100644
--- a/libavcodec/v4l2_request_h264.c
+++ b/libavcodec/v4l2_request_h264.c
@@ -19,6 +19,7 @@
@ -577,7 +604,7 @@ index fb9913922d..b826c9d356 100644
typedef struct V4L2RequestControlsH264 {
struct v4l2_ctrl_h264_sps sps;
diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c
index 38969d77fb..b73eb2ab03 100644
index da1fd666d7..94977c5d0e 100644
--- a/libavcodec/v4l2_request_hevc.c
+++ b/libavcodec/v4l2_request_hevc.c
@@ -19,6 +19,7 @@
@ -730,3 +757,6 @@ index 0000000000..53cba826e4
+};
+
+#endif
--
2.24.0

View File

@ -1,7 +1,7 @@
From 0c4c87e72463da1a4bf45032e4db3c2c86d6d8d8 Mon Sep 17 00:00:00 2001
From 6b20e11c96907fb474b1bf33615223bf79eba9c0 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 29 Apr 2019 22:08:59 +0000
Subject: [PATCH] hwcontext_drm: do not require drm device
Subject: [PATCH 08/12] hwcontext_drm: do not require drm device
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
@ -24,3 +24,6 @@ index 32cbde82eb..aa4794c5e6 100644
hwctx->fd = open(device, O_RDWR);
if (hwctx->fd < 0)
return AVERROR(errno);
--
2.24.0

View File

@ -1,7 +1,7 @@
From 3d50f433609688b6d4ffb2bcec41507f7f507dc2 Mon Sep 17 00:00:00 2001
From 4c1ce1fde5ca6d3e80bb0d5ab44f2e05f8372db0 Mon Sep 17 00:00:00 2001
From: Ezequiel Garcia <ezequiel@collabora.com>
Date: Wed, 20 Feb 2019 11:18:00 -0300
Subject: [PATCH] avcodec/h264: parse idr_pic_id
Subject: [PATCH 09/12] avcodec/h264: parse idr_pic_id
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
@ -37,10 +37,10 @@ index b0b42b7672..38efab5c60 100644
int chroma_qp[2]; // QPc
int qp_thresh; ///< QP threshold to skip loopfilter
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
index b826c9d356..a49773b228 100644
index ca306b6a3f..f21c8b3508 100644
--- a/libavcodec/v4l2_request_h264.c
+++ b/libavcodec/v4l2_request_h264.c
@@ -284,7 +284,7 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *
@@ -301,7 +301,7 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *
.pic_parameter_set_id = sl->pps_id,
.colour_plane_id = 0, /* what is this? */
.frame_num = h->poc.frame_num,
@ -49,3 +49,6 @@ index b826c9d356..a49773b228 100644
.pic_order_cnt_lsb = sl->poc_lsb,
.delta_pic_order_cnt_bottom = sl->delta_poc_bottom,
.delta_pic_order_cnt0 = sl->delta_poc[0],
--
2.24.0

View File

@ -1,7 +1,7 @@
From 2f915e957c6bc5887cc24a8762fdadea17359f57 Mon Sep 17 00:00:00 2001
From 0a7b4a2cffae5d37b753b3e4cc8cadd7204ef5f5 Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@collabora.com>
Date: Wed, 22 May 2019 14:44:22 +0200
Subject: [PATCH] avcodec/h264: parse ref_pic_marking_size_in_bits and
Subject: [PATCH 10/12] avcodec/h264: parse ref_pic_marking_size_in_bits and
pic_order_cnt_bit_size
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
@ -71,10 +71,10 @@ index 38efab5c60..8e894f565b 100644
int max_pic_num;
} H264SliceContext;
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
index a49773b228..229df6969d 100644
index f21c8b3508..1a7fb873a0 100644
--- a/libavcodec/v4l2_request_h264.c
+++ b/libavcodec/v4l2_request_h264.c
@@ -292,9 +292,9 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *
@@ -309,9 +309,9 @@ static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *
.redundant_pic_cnt = sl->redundant_pic_count,
/* Size in bits of dec_ref_pic_marking() syntax element. */
@ -86,3 +86,6 @@ index a49773b228..229df6969d 100644
.cabac_init_idc = sl->cabac_init_idc,
.slice_qp_delta = sl->qscale - pps->init_qp,
--
2.24.0

View File

@ -1,7 +1,8 @@
From 45df99d31062e068073cf899dce559e334c9127f Mon Sep 17 00:00:00 2001
From 1a2197eea4da8f118726963e0c74647532029306 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Fri, 24 May 2019 22:58:24 +0000
Subject: [PATCH] HACK: add dpb flags for reference usage and field picture
Subject: [PATCH 11/12] HACK: add dpb flags for reference usage and field
picture
This or something similar needs to be upstreamed to kernel h264 ctrls
@ -27,10 +28,10 @@ index e877bf1d53..76020ebd1e 100644
struct v4l2_h264_dpb_entry {
__u64 reference_ts;
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
index 229df6969d..7f345b1955 100644
index 1a7fb873a0..13fac3f6f9 100644
--- a/libavcodec/v4l2_request_h264.c
+++ b/libavcodec/v4l2_request_h264.c
@@ -65,10 +65,13 @@ static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, const H264Picture
@@ -66,10 +66,13 @@ static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, const H264Picture
entry->frame_num = pic->frame_num;
entry->pic_num = pic->pic_id;
entry->flags = V4L2_H264_DPB_ENTRY_FLAG_VALID;
@ -44,7 +45,7 @@ index 229df6969d..7f345b1955 100644
if (pic->field_poc[0] != INT_MAX)
entry->top_field_order_cnt = pic->field_poc[0];
if (pic->field_poc[1] != INT_MAX)
@@ -108,7 +111,8 @@ static uint8_t get_dpb_index(struct v4l2_ctrl_h264_decode_params *decode, const
@@ -109,7 +112,8 @@ static uint8_t get_dpb_index(struct v4l2_ctrl_h264_decode_params *decode, const
struct v4l2_h264_dpb_entry *entry = &decode->dpb[i];
if ((entry->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID) &&
entry->reference_ts == timestamp)
@ -54,3 +55,6 @@ index 229df6969d..7f345b1955 100644
}
return 0;
--
2.24.0

View File

@ -0,0 +1,72 @@
From a205c82e430dafd90485b804ce40c1b42cbf9edf Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 9 Nov 2019 10:02:43 +0000
Subject: [PATCH 12/12] WIP: v4l2-request: rolling timestamps
---
libavcodec/v4l2_request.c | 10 +++++++---
libavcodec/v4l2_request.h | 1 +
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c
index 1dabf77689..611c22f8b6 100644
--- a/libavcodec/v4l2_request.c
+++ b/libavcodec/v4l2_request.c
@@ -105,12 +105,14 @@ static int v4l2_request_queue_buffer(V4L2RequestContext *ctx, int request_fd, V4
.type = buf->buffer.type,
.memory = buf->buffer.memory,
.index = buf->index,
- .timestamp.tv_usec = buf->index + 1,
+ .timestamp.tv_usec = ctx->timestamp,
.bytesused = buf->used,
.request_fd = request_fd,
.flags = ((request_fd >= 0) ? V4L2_BUF_FLAG_REQUEST_FD : 0) | flags,
};
+ buf->buffer.timestamp = buffer.timestamp;
+
if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type)) {
planes[0].bytesused = buf->used;
buffer.bytesused = 0;
@@ -200,6 +202,9 @@ static int v4l2_request_queue_decode(AVCodecContext *avctx, AVFrame *frame, stru
av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p used=%u controls=%d index=%d fd=%d request_fd=%d first_slice=%d last_slice=%d\n", __func__, avctx, req->output.used, count, req->capture.index, req->capture.fd, req->request_fd, first_slice, last_slice);
+ if (first_slice)
+ ctx->timestamp++;
+
ret = v4l2_request_set_controls(ctx, req->request_fd, control, count);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "%s: set controls failed for request %d, %s (%d)\n", __func__, req->request_fd, strerror(errno), errno);
@@ -651,6 +656,7 @@ int ff_v4l2_request_init(AVCodecContext *avctx, uint32_t pixelformat, uint32_t b
ctx->media_fd = -1;
ctx->video_fd = -1;
+ ctx->timestamp = 0;
udev = udev_new();
if (!udev) {
@@ -784,8 +790,6 @@ static int v4l2_request_buffer_alloc(AVCodecContext *avctx, V4L2RequestBuffer *b
return ret;
}
- buf->buffer.timestamp.tv_usec = buf->index + 1;
-
if (V4L2_TYPE_IS_OUTPUT(type)) {
void *addr = mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, ctx->video_fd, V4L2_TYPE_IS_MULTIPLANAR(type) ? buf->buffer.m.planes[0].m.mem_offset : buf->buffer.m.offset);
if (addr == MAP_FAILED) {
diff --git a/libavcodec/v4l2_request.h b/libavcodec/v4l2_request.h
index d4146bd4ee..72698f6f3c 100644
--- a/libavcodec/v4l2_request.h
+++ b/libavcodec/v4l2_request.h
@@ -28,6 +28,7 @@ typedef struct V4L2RequestContext {
int media_fd;
enum v4l2_buf_type output_type;
struct v4l2_format format;
+ int timestamp;
} V4L2RequestContext;
typedef struct V4L2RequestBuffer {
--
2.24.0

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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