Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allwinner: Rework HW decoding #3972

Merged
merged 2 commits into from Nov 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -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>
---
Expand Down Expand Up @@ -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

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

Expand Down Expand Up @@ -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.
+ *
Expand Down Expand Up @@ -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 = {
Expand All @@ -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)) {
Expand Down Expand Up @@ -308,15 +308,15 @@ 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];
+ struct timeval tv = { 2, 0 };
+ 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) {
Expand All @@ -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?
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -866,6 +889,7 @@ index 0000000000..bf9d049eff
+ }
+
+ buf->index = buffers.index;
+ buf->capabilities = buffers.capabilities;
+ buf->used = 0;
+
+ buf->buffer.type = type;
Expand Down Expand Up @@ -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.
+ *
Expand Down Expand Up @@ -1081,6 +1105,7 @@ index 0000000000..1f45772d8b
+ uint32_t height;
+ uint32_t size;
+ uint32_t used;
+ uint32_t capabilities;
+ struct v4l2_buffer buffer;
+} V4L2RequestBuffer;
+
Expand All @@ -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);
Expand All @@ -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

@@ -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>
---
Expand Down Expand Up @@ -242,3 +242,6 @@ index 0000000000..782b9c2471
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};
--
2.24.0

@@ -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>
Expand All @@ -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
Expand Down Expand Up @@ -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.
+ *
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand All @@ -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[] = {
+ {
Expand Down Expand Up @@ -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));
+}
+
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -522,3 +545,6 @@ index 0000000000..fb9913922d
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};
--
2.24.0