[FFmpeg-devel] [PATCH 1/4] vaapi_encode: Move block size calculation after entrypoint selection
Mark Thompson
sw at jkqxz.net
Thu Mar 5 02:25:25 EET 2020
The block size can be dependent on the profile and entrypoint selected.
It defaults to 16x16, with codecs able to override this choice with their
own function.
---
libavcodec/vaapi_encode.c | 14 ++++++++++++++
libavcodec/vaapi_encode.h | 6 ++++++
libavcodec/vaapi_encode_h265.c | 32 ++++++++++++++++++++++++++------
libavcodec/vaapi_encode_mjpeg.c | 16 +++++++++++++---
libavcodec/vaapi_encode_mpeg2.c | 3 ---
libavcodec/vaapi_encode_vp8.c | 3 ---
libavcodec/vaapi_encode_vp9.c | 14 ++++++++++----
7 files changed, 69 insertions(+), 19 deletions(-)
diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index 8ff720e395..93bbed4539 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -1840,6 +1840,8 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx)
return 0;
}
+ av_assert0(ctx->slice_block_height > 0 && ctx->slice_block_width > 0);
+
ctx->slice_block_rows = (avctx->height + ctx->slice_block_height - 1) /
ctx->slice_block_height;
ctx->slice_block_cols = (avctx->width + ctx->slice_block_width - 1) /
@@ -2237,6 +2239,18 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
if (err < 0)
goto fail;
+ if (ctx->codec->block_size) {
+ ctx->codec->block_size(avctx);
+ } else {
+ // Assume 16x16 blocks.
+ ctx->surface_width = FFALIGN(avctx->width, 16);
+ ctx->surface_height = FFALIGN(avctx->height, 16);
+ if (ctx->codec->flags & FLAG_SLICE_CONTROL) {
+ ctx->slice_block_width = 16;
+ ctx->slice_block_height = 16;
+ }
+ }
+
err = vaapi_encode_init_rate_control(avctx);
if (err < 0)
goto fail;
diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h
index b9a3defd72..583be9c845 100644
--- a/libavcodec/vaapi_encode.h
+++ b/libavcodec/vaapi_encode.h
@@ -355,6 +355,12 @@ typedef struct VAAPIEncodeType {
// factor depending on RC mode.
int default_quality;
+ // Determine block sizes for surface alignment and slices. This may
+ // need to query the profile and entrypoint, which will be available
+ // when this function is called. If not set, assume that all blocks
+ // are 16x16 and that surfaces should be aligned to match this.
+ void (*block_size)(AVCodecContext *avctx);
+
// Perform any extra codec-specific configuration after the
// codec context is initialised (set up the private data and
// add any necessary global parameters).
diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index 538862a9d5..9a78dfb4f7 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -55,6 +55,10 @@ typedef struct VAAPIEncodeH265Picture {
typedef struct VAAPIEncodeH265Context {
VAAPIEncodeContext common;
+ // Encoder features.
+ uint32_t ctu_size;
+ uint32_t min_cb_size;
+
// User options.
int qp;
int aud;
@@ -1062,6 +1066,27 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
return 0;
}
+static av_cold void vaapi_encode_h265_block_size(AVCodecContext *avctx)
+{
+ VAAPIEncodeContext *ctx = avctx->priv_data;
+ VAAPIEncodeH265Context *priv = avctx->priv_data;
+
+ if (!priv->ctu_size) {
+ priv->ctu_size = 32;
+ priv->min_cb_size = 16;
+ }
+ av_log(avctx, AV_LOG_VERBOSE, "Using CTU size %dx%d, "
+ "min CB size %dx%d.\n", priv->ctu_size, priv->ctu_size,
+ priv->min_cb_size, priv->min_cb_size);
+
+ ctx->surface_width = FFALIGN(avctx->width, priv->min_cb_size);
+ ctx->surface_height = FFALIGN(avctx->height, priv->min_cb_size);
+
+ ctx->slice_block_width = ctx->slice_block_height = priv->ctu_size;
+
+ return;
+}
+
static av_cold int vaapi_encode_h265_configure(AVCodecContext *avctx)
{
VAAPIEncodeContext *ctx = avctx->priv_data;
@@ -1127,6 +1152,7 @@ static const VAAPIEncodeType vaapi_encode_type_h265 = {
.default_quality = 25,
+ .block_size = &vaapi_encode_h265_block_size,
.configure = &vaapi_encode_h265_configure,
.picture_priv_data_size = sizeof(VAAPIEncodeH265Picture),
@@ -1172,12 +1198,6 @@ static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx)
VA_ENC_PACKED_HEADER_SLICE | // Slice headers.
VA_ENC_PACKED_HEADER_MISC; // SEI
- ctx->surface_width = FFALIGN(avctx->width, 16);
- ctx->surface_height = FFALIGN(avctx->height, 16);
-
- // CTU size is currently hard-coded to 32.
- ctx->slice_block_width = ctx->slice_block_height = 32;
-
if (priv->qp > 0)
ctx->explicit_qp = priv->qp;
diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c
index bd029cc903..0d992d6f44 100644
--- a/libavcodec/vaapi_encode_mjpeg.c
+++ b/libavcodec/vaapi_encode_mjpeg.c
@@ -434,6 +434,18 @@ static int vaapi_encode_mjpeg_init_slice_params(AVCodecContext *avctx,
return 0;
}
+static av_cold void vaapi_encode_mjpeg_block_size(AVCodecContext *avctx)
+{
+ VAAPIEncodeContext *ctx = avctx->priv_data;
+ const AVPixFmtDescriptor *desc;
+
+ desc = av_pix_fmt_desc_get(ctx->input_frames->sw_format);
+ av_assert0(desc);
+
+ ctx->surface_width = FFALIGN(avctx->width, 8 << desc->log2_chroma_w);
+ ctx->surface_height = FFALIGN(avctx->height, 8 << desc->log2_chroma_h);
+}
+
static av_cold int vaapi_encode_mjpeg_configure(AVCodecContext *avctx)
{
VAAPIEncodeContext *ctx = avctx->priv_data;
@@ -483,6 +495,7 @@ static const VAAPIEncodeType vaapi_encode_type_mjpeg = {
.flags = FLAG_CONSTANT_QUALITY_ONLY |
FLAG_INTRA_ONLY,
+ .block_size = &vaapi_encode_mjpeg_block_size,
.configure = &vaapi_encode_mjpeg_configure,
.default_quality = 80,
@@ -509,9 +522,6 @@ static av_cold int vaapi_encode_mjpeg_init(AVCodecContext *avctx)
ctx->desired_packed_headers =
VA_ENC_PACKED_HEADER_RAW_DATA;
- ctx->surface_width = FFALIGN(avctx->width, 8);
- ctx->surface_height = FFALIGN(avctx->height, 8);
-
return ff_vaapi_encode_init(avctx);
}
diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c
index bac9ea1fa6..442321b55c 100644
--- a/libavcodec/vaapi_encode_mpeg2.c
+++ b/libavcodec/vaapi_encode_mpeg2.c
@@ -623,9 +623,6 @@ static av_cold int vaapi_encode_mpeg2_init(AVCodecContext *avctx)
ctx->desired_packed_headers = VA_ENC_PACKED_HEADER_SEQUENCE |
VA_ENC_PACKED_HEADER_PICTURE;
- ctx->surface_width = FFALIGN(avctx->width, 16);
- ctx->surface_height = FFALIGN(avctx->height, 16);
-
return ff_vaapi_encode_init(avctx);
}
diff --git a/libavcodec/vaapi_encode_vp8.c b/libavcodec/vaapi_encode_vp8.c
index 6e7bf9d106..93d8b57316 100644
--- a/libavcodec/vaapi_encode_vp8.c
+++ b/libavcodec/vaapi_encode_vp8.c
@@ -210,9 +210,6 @@ static av_cold int vaapi_encode_vp8_init(AVCodecContext *avctx)
// adding them anyway.
ctx->desired_packed_headers = 0;
- ctx->surface_width = FFALIGN(avctx->width, 16);
- ctx->surface_height = FFALIGN(avctx->height, 16);
-
return ff_vaapi_encode_init(avctx);
}
diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c
index d7f415d704..19093bfa71 100644
--- a/libavcodec/vaapi_encode_vp9.c
+++ b/libavcodec/vaapi_encode_vp9.c
@@ -176,6 +176,15 @@ static int vaapi_encode_vp9_init_picture_params(AVCodecContext *avctx,
return 0;
}
+static av_cold void vaapi_encode_vp9_block_size(AVCodecContext *avctx)
+{
+ VAAPIEncodeContext *ctx = avctx->priv_data;
+
+ // Surfaces must be aligned to 64x64 superblock boundaries.
+ ctx->surface_width = FFALIGN(avctx->width, 64);
+ ctx->surface_height = FFALIGN(avctx->height, 64);
+}
+
static av_cold int vaapi_encode_vp9_configure(AVCodecContext *avctx)
{
VAAPIEncodeContext *ctx = avctx->priv_data;
@@ -223,6 +232,7 @@ static const VAAPIEncodeType vaapi_encode_type_vp9 = {
.picture_priv_data_size = sizeof(VAAPIEncodeVP9Picture),
+ .block_size = &vaapi_encode_vp9_block_size,
.configure = &vaapi_encode_vp9_configure,
.sequence_params_size = sizeof(VAEncSequenceParameterBufferVP9),
@@ -243,10 +253,6 @@ static av_cold int vaapi_encode_vp9_init(AVCodecContext *avctx)
// can write its own headers and there is no metadata to include.
ctx->desired_packed_headers = 0;
- // Surfaces must be aligned to superblock boundaries.
- ctx->surface_width = FFALIGN(avctx->width, 64);
- ctx->surface_height = FFALIGN(avctx->height, 64);
-
return ff_vaapi_encode_init(avctx);
}
--
2.25.0
More information about the ffmpeg-devel
mailing list