From patchwork Sun Sep 23 21:52:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Thompson X-Patchwork-Id: 10461 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:1286:0:0:0:0:0 with SMTP id 6-v6csp1850861jap; Sun, 23 Sep 2018 14:53:15 -0700 (PDT) X-Google-Smtp-Source: ACcGV61Ds0Kjtr9oJDZ7lEqZX12INgbffVIew97sy8fXbEcNY6oeByet4p8FoSoh2u6oHn5NYscz X-Received: by 2002:adf:c88b:: with SMTP id k11-v6mr3506265wrh.6.1537739595013; Sun, 23 Sep 2018 14:53:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1537739594; cv=none; d=google.com; s=arc-20160816; b=f29d26yqRmAyEy+L0+Yzz2MYEvc+3eU2XX1OIfT53PHmOirUWaoNaI77FPVkc4cyY3 uyyh0XoQupLp8MebTt3iWnzMMy89/QNpEBgQBs4R5WL+RMHjJjwQVRC61nuQgx9KpeCl owzcAZgVJSd7tpyWY3JyvWwhUEVkxA85gwePaN6SczOG2W6VK42md9LzlIYSsGaEyYEl oR5LvE5R9uTp6MdBsKPVt+5TomOBoHbDXOow55G9eoG5p+mo/kuwpiiaRJ+P2r+RURmE JnkGmlsheXyveXOdyXXh7aIu9wBS7fNy8zIfnlIRdeTf2s6TUwEwatGN7Iy2jNoDiUqH D3Uw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:message-id:date:to:from:dkim-signature :delivered-to; bh=uph6Fth+SW0IiDuJxdAOgpTy5RN+Xv3YvJ4EObnydOo=; b=NooAV3njAG6T96LVCtBtlU1lGgb03lUgG6lSZdZdWiHLAokzDx+wxkdd5VYZiZWfHJ +cxEEs/MtsfbUYkuxMao6clrI8ISVh+sxN/QsiOnwq8dnIIr7fufOvnL4DJ2fg6UeCAa 0LVuzlBHccdwQymvDOGzNrFvEX4rykbB/Lu/S2vwpFhwuw/FlTinBGBiNbU1o61sA/a3 DRVNAkjwgmPiEiyCaLJfCe2ONGuJV1mxiVfFmJHL1iZBRKbRjmrIArYQYYM/ZpxeQtWV q7Ea+diy03Gzhu42t9wtOSgMddz+d4eXx8TtW5NxORezOXJNBq1eL6t9n0oWL2lswKWx 9/sw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@jkqxz-net.20150623.gappssmtp.com header.s=20150623 header.b=xWBcJdwp; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id k3-v6si5913347wrg.33.2018.09.23.14.53.14; Sun, 23 Sep 2018 14:53:14 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@jkqxz-net.20150623.gappssmtp.com header.s=20150623 header.b=xWBcJdwp; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5C47668A642; Mon, 24 Sep 2018 00:52:57 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 747A068A497 for ; Mon, 24 Sep 2018 00:52:51 +0300 (EEST) Received: by mail-wr1-f47.google.com with SMTP id z3-v6so5939617wrr.13 for ; Sun, 23 Sep 2018 14:53:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jkqxz-net.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id; bh=1palkolrURLzDzBGW35EnV3I8YF3TB0d4NwITnPAR70=; b=xWBcJdwpOwTNBBKzAKiyh+sp7MpvYfOJajQAWlTvZJDs/nKAzRnz2rEio1CUoSCmjI 5ZbSIT4K9M/JKCbMSfvbMZIHOqOHL+mSxnQnoyWG3CDJvRivWMCk2vOlVBvbMZ7evbmF Vp7CkGZl4eEt0y6iE3+EVaO7IGTxtzKVvAQWu6aIyAnpERbTBN6Jrj0DRZTn8gca+jp8 00ol8mUdz27rLbGo9qCQI7nIOCD9X/ynbN4o1JEImnXIprK1JcldIs99TpWq3vhZ+DIX aI52ROAZwi3uQHor9n8xjz3GdVwgPaTOqcq3Z2gMsBvhlNP93IJbKKwZyDoxGS8dhOtH I7ug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=1palkolrURLzDzBGW35EnV3I8YF3TB0d4NwITnPAR70=; b=UU9qv0PBuE9V/yMBbTEP1tf1fDFFwbwvR6lIzqNR1SoIV7z8KTMKtsyQaOt8QyBSDc Zvd0Ws1tDWbHjWuB8c6QbpDaFBO/0SyeOfJTPxle9j0eM1i7S0zFFapGdsHkK5c7QR36 TBVx8FkP3cmcGK0QD2BuMu4QqZBcISqIeX7JtHx5XkAds78X+zAiaJC7ueTI4iQyzMe0 kXWQzfdVbbtpury5bFfCRPmeP9Dm/9yc/9Z58IXDS+Ba+nBb+XAy2+msL4yc7XJUMxKr z4mv173OrWPGhcTr3YH4+u/ekF9xbWdUzdg4NG0lFjXQ38FRRcB6LDsIJMjT4gPLXtzZ /TLg== X-Gm-Message-State: ABuFfojXMTRJNkk1bLN9ntt0WQ3SlPHBNfcKvmmSDTWfQ39Ep2NYRTqr DNH3Mz8/7sQxeJFwHBq5kywPMt0Cn/Y= X-Received: by 2002:adf:959a:: with SMTP id p26-v6mr5776020wrp.202.1537739585751; Sun, 23 Sep 2018 14:53:05 -0700 (PDT) Received: from rywe.jkqxz.net (cpc91242-cmbg18-2-0-cust650.5-4.cable.virginm.net. [82.8.130.139]) by smtp.gmail.com with ESMTPSA id 124-v6sm14960730wmk.20.2018.09.23.14.53.04 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 23 Sep 2018 14:53:04 -0700 (PDT) From: Mark Thompson To: ffmpeg-devel@ffmpeg.org Date: Sun, 23 Sep 2018 22:52:56 +0100 Message-Id: <20180923215300.2077-1-sw@jkqxz.net> X-Mailer: git-send-email 2.18.0 Subject: [FFmpeg-devel] [PATCH v2 1/5] vaapi_encode: Support configurable slices X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" This adds common code to query driver support and set appropriate address/size information for each slice. It only supports rectangular slices for now, since that is the most common use-case. --- doc/encoders.texi | 2 + libavcodec/vaapi_encode.c | 151 +++++++++++++++++++++++++++++++++++++- libavcodec/vaapi_encode.h | 22 ++++++ 3 files changed, 173 insertions(+), 2 deletions(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index 8d184f72f8..899faac49b 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -2598,6 +2598,8 @@ Size / quality tradeoff: higher values are smaller / worse quality. @option{b_qfactor} / @option{b_quant_factor} @item @option{b_qoffset} / @option{b_quant_offset} +@item +@option{slices} @end itemize All encoders support the following options: diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 2c34cdce2c..2d33aa5ec3 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -319,16 +319,60 @@ static int vaapi_encode_issue(AVCodecContext *avctx, } } + if (pic->nb_slices == 0) + pic->nb_slices = ctx->nb_slices; if (pic->nb_slices > 0) { + int rounding; + pic->slices = av_mallocz_array(pic->nb_slices, sizeof(*pic->slices)); if (!pic->slices) { err = AVERROR(ENOMEM); goto fail; } + + for (i = 0; i < pic->nb_slices; i++) + pic->slices[i].row_size = ctx->slice_size; + + rounding = ctx->slice_block_rows - ctx->nb_slices * ctx->slice_size; + if (rounding > 0) { + // Place rounding error at top and bottom of frame. + av_assert0(rounding < pic->nb_slices); + // Some Intel drivers contain a bug where the encoder will fail + // if the last slice is smaller than the one before it. Since + // that's straightforward to avoid here, just do so. + if (rounding <= 2) { + for (i = 0; i < rounding; i++) + ++pic->slices[i].row_size; + } else { + for (i = 0; i < (rounding + 1) / 2; i++) + ++pic->slices[pic->nb_slices - i - 1].row_size; + for (i = 0; i < rounding / 2; i++) + ++pic->slices[i].row_size; + } + } else if (rounding < 0) { + // Remove rounding error from last slice only. + av_assert0(rounding < ctx->slice_size); + pic->slices[pic->nb_slices - 1].row_size += rounding; + } } for (i = 0; i < pic->nb_slices; i++) { slice = &pic->slices[i]; slice->index = i; + if (i == 0) { + slice->row_start = 0; + slice->block_start = 0; + } else { + const VAAPIEncodeSlice *prev = &pic->slices[i - 1]; + slice->row_start = prev->row_start + prev->row_size; + slice->block_start = prev->block_start + prev->block_size; + } + slice->block_size = slice->row_size * ctx->slice_block_cols; + + av_log(avctx, AV_LOG_DEBUG, "Slice %d: %d-%d (%d rows), " + "%d-%d (%d blocks).\n", i, slice->row_start, + slice->row_start + slice->row_size - 1, slice->row_size, + slice->block_start, slice->block_start + slice->block_size - 1, + slice->block_size); if (ctx->codec->slice_params_size > 0) { slice->codec_slice_params = av_mallocz(ctx->codec->slice_params_size); @@ -1014,8 +1058,7 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) VAEntrypoint *va_entrypoints = NULL; VAStatus vas; const VAEntrypoint *usable_entrypoints; - const VAAPIEncodeProfile *profile; - const AVPixFmtDescriptor *desc; + const VAAPIEncodeProfile *profile; const AVPixFmtDescriptor *desc; VAConfigAttrib rt_format_attr; const VAAPIEncodeRTFormat *rt_format; const char *profile_string, *entrypoint_string; @@ -1444,6 +1487,106 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) return 0; } +static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAConfigAttrib attr[2] = { { VAConfigAttribEncMaxSlices }, + { VAConfigAttribEncSliceStructure } }; + VAStatus vas; + uint32_t max_slices, slice_structure; + int req_slices; + + if (!(ctx->codec->flags & FLAG_SLICE_CONTROL)) { + if (avctx->slices > 0) { + av_log(avctx, AV_LOG_WARNING, "Multiple slices were requested " + "but this codec does not support controlling slices.\n"); + } + return 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) / + ctx->slice_block_width; + + if (avctx->slices <= 1) { + ctx->nb_slices = 1; + ctx->slice_size = ctx->slice_block_rows; + return 0; + } + + vas = vaGetConfigAttributes(ctx->hwctx->display, + ctx->va_profile, + ctx->va_entrypoint, + attr, FF_ARRAY_ELEMS(attr)); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query slice " + "attributes: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR_EXTERNAL; + } + max_slices = attr[0].value; + slice_structure = attr[1].value; + if (max_slices == VA_ATTRIB_NOT_SUPPORTED || + slice_structure == VA_ATTRIB_NOT_SUPPORTED) { + av_log(avctx, AV_LOG_ERROR, "Driver does not support encoding " + "pictures as multiple slices.\n."); + return AVERROR(EINVAL); + } + + // For fixed-size slices currently we only support whole rows, making + // rectangular slices. This could be extended to arbitrary runs of + // blocks, but since slices tend to be a conformance requirement and + // most cases (such as broadcast or bluray) want rectangular slices + // only it would need to be gated behind another option. + if (avctx->slices > ctx->slice_block_rows) { + av_log(avctx, AV_LOG_WARNING, "Not enough rows to use " + "configured number of slices (%d < %d); using " + "maximum.\n", ctx->slice_block_rows, avctx->slices); + req_slices = ctx->slice_block_rows; + } else { + req_slices = avctx->slices; + } + if (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS || + slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) { + ctx->nb_slices = req_slices; + ctx->slice_size = ctx->slice_block_rows / ctx->nb_slices; + } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) { + int k; + for (k = 1;; k *= 2) { + if (2 * k * (req_slices - 1) + 1 >= ctx->slice_block_rows) + break; + } + ctx->nb_slices = (ctx->slice_block_rows + k - 1) / k; + ctx->slice_size = k; +#if VA_CHECK_VERSION(1, 0, 0) + } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS) { + ctx->nb_slices = ctx->slice_block_rows; + ctx->slice_size = 1; +#endif + } else { + av_log(avctx, AV_LOG_ERROR, "Driver does not support any usable " + "slice structure modes (%#x).\n", slice_structure); + return AVERROR(EINVAL); + } + + if (ctx->nb_slices > avctx->slices) { + av_log(avctx, AV_LOG_WARNING, "Slice count rounded up to " + "%d (from %d) due to driver constraints on slice " + "structure.\n", ctx->nb_slices, avctx->slices); + } + if (ctx->nb_slices > max_slices) { + av_log(avctx, AV_LOG_ERROR, "Driver does not support " + "encoding with %d slices (max %"PRIu32").\n", + ctx->nb_slices, max_slices); + return AVERROR(EINVAL); + } + + av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices " + "(default size %d block rows).\n", + ctx->nb_slices, ctx->slice_size); + return 0; +} + static av_cold int vaapi_encode_init_packed_headers(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -1734,6 +1877,10 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) if (err < 0) goto fail; + err = vaapi_encode_init_slice_structure(avctx); + if (err < 0) + goto fail; + err = vaapi_encode_init_packed_headers(avctx); if (err < 0) goto fail; diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 091889f9ae..271d4ef518 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -52,6 +52,10 @@ enum { typedef struct VAAPIEncodeSlice { int index; + int row_start; + int row_size; + int block_start; + int block_size; void *priv_data; void *codec_slice_params; } VAAPIEncodeSlice; @@ -125,6 +129,10 @@ typedef struct VAAPIEncodeContext { int surface_width; int surface_height; + // The block size for slice calculations. + int slice_block_width; + int slice_block_height; + // Everything above this point must be set before calling // ff_vaapi_encode_init(). @@ -224,6 +232,12 @@ typedef struct VAAPIEncodeContext { int64_t dts_pts_diff; int64_t ts_ring[MAX_REORDER_DELAY * 3]; + // Slice structure. + int slice_block_rows; + int slice_block_cols; + int nb_slices; + int slice_size; + // Frame type decision. int gop_size; int p_per_i; @@ -234,11 +248,19 @@ typedef struct VAAPIEncodeContext { int end_of_stream; } VAAPIEncodeContext; +enum { + // Codec supports controlling the subdivision of pictures into slices. + FLAG_SLICE_CONTROL = 1 << 0, +}; + typedef struct VAAPIEncodeType { // List of supported profiles and corresponding VAAPI profiles. // (Must end with FF_PROFILE_UNKNOWN.) const VAAPIEncodeProfile *profiles; + // Codec feature flags. + int flags; + // Perform any extra codec-specific configuration after the // codec context is initialised (set up the private data and // add any necessary global parameters).