From patchwork Mon Mar 23 14:24:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Fu, Linjie" X-Patchwork-Id: 18368 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id C6CA644B609 for ; Mon, 23 Mar 2020 16:29:45 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 94A2968B6A7; Mon, 23 Mar 2020 16:29:45 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id F0E6D68B63A for ; Mon, 23 Mar 2020 16:29:38 +0200 (EET) IronPort-SDR: BK647GUk32pF+wI4xET0iJmMSMvsbjppAPafLgh2zzLxxaZ4oBHToV8YvTSPR+0akpIFW4Q63U Dvu0FtXNxc1w== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Mar 2020 07:29:36 -0700 IronPort-SDR: RT6cA2CQ7oDP9VrYIp+xHNOGXT2xX1lqLOXmJbX36plB43IChp/vIqSOifj/gDwWzsLpVB7mwY hAWCSiT7jaMQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,296,1580803200"; d="scan'208";a="269892288" Received: from icl-dev.sh.intel.com ([10.239.158.73]) by fmsmga004.fm.intel.com with ESMTP; 23 Mar 2020 07:29:35 -0700 From: Linjie Fu To: ffmpeg-devel@ffmpeg.org Date: Mon, 23 Mar 2020 22:24:00 +0800 Message-Id: <1584973440-31904-1-git-send-email-linjie.fu@intel.com> X-Mailer: git-send-email 2.7.4 Subject: [FFmpeg-devel] [PATCH 1/3] lavc/vaapi_encode: wrap slice codes into row slice functions 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 Cc: Linjie Fu MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Wrap current whole-row slice codes into following functions: - vaapi_encode_make_row_slice() - vaapi_encode_init_row_slice_structure() Signed-off-by: Linjie Fu --- libavcodec/vaapi_encode.c | 184 ++++++++++++++++++++++++++-------------------- 1 file changed, 106 insertions(+), 78 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 8ff720e..8b48379 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -157,6 +157,61 @@ static int vaapi_encode_wait(AVCodecContext *avctx, return 0; } +static int vaapi_encode_make_row_slice(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeSlice *slice; + int i, rounding; + + 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); + } + + return 0; +} + static int vaapi_encode_issue(AVCodecContext *avctx, VAAPIEncodePicture *pic) { @@ -340,57 +395,17 @@ 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; - } + vaapi_encode_make_row_slice(avctx, pic); } + 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); @@ -1823,6 +1838,51 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) return 0; } +static av_cold int vaapi_encode_init_row_slice_structure(AVCodecContext *avctx, + uint32_t slice_structure) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + int req_slices; + + // 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); + } + + return 0; +} + static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -1830,7 +1890,7 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { VAConfigAttribEncSliceStructure } }; VAStatus vas; uint32_t max_slices, slice_structure; - int req_slices; + int ret; if (!(ctx->codec->flags & FLAG_SLICE_CONTROL)) { if (avctx->slices > 0) { @@ -1869,41 +1929,9 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) 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); - } + ret = vaapi_encode_init_row_slice_structure(avctx, slice_structure); + if (ret < 0) + return ret; if (ctx->nb_slices > avctx->slices) { av_log(avctx, AV_LOG_WARNING, "Slice count rounded up to " From patchwork Mon Mar 23 14:24:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Fu, Linjie" X-Patchwork-Id: 18370 Delivered-To: andriy.gelman@gmail.com Received: by 2002:a0c:ab15:0:0:0:0:0 with SMTP id h21csp3126730qvb; Mon, 23 Mar 2020 07:30:03 -0700 (PDT) X-Google-Smtp-Source: ADFU+vufEX8IUQfPVKvJUF1fBKW3qQDDpaUo/7oPYAiVGCF7WSgJvnTuTDhYlUwbxqzn2XV5x305 X-Received: by 2002:aa7:c2cc:: with SMTP id m12mr21957375edp.11.1584973803155; Mon, 23 Mar 2020 07:30:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1584973803; cv=none; d=google.com; s=arc-20160816; b=Qg49NyPkEuwLpONRwEyIqSKDNWNUJA2Xi0Po7WJv42rvYSHNxHN5yLfZjRo2HycmJB h6Zflui98yXJHuKxlYvQwP6v0YIl62XfZjDFNTKsQVWbaWI9N+1+wuHsfr/Dqgm0HOx8 JJxJ5FbiocXqKeTZ29M+CvBGOk51RgqIfK0TJHNBRJj5Dwft3teVpbIx2Tk8urvlqOyE HqIoXjYvg7TxRhCOJeoJ0ByZW5mzwMk5YhWcvZpBLBiclOD21kHJA8iCZn/u9Onw32Rb X4uq3p0PeNBOgJ0Rzi2q/EnLL5c0xkbolOohHM+fN2KoGItvSrTTix5OXMRgA1KGllDe RUoA== 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:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:message-id:date:to:from:ironport-sdr :ironport-sdr:delivered-to; bh=oXcOFjPwLehUPG3CoCJhbq9cuLUQQ+w2aulPfLi1pgA=; b=VDOUiuXRcTPxPuA/QBvLtsWOr70izafUHXhyRivgScT/hTuItnq/nGCfgqmIKyVJZf AqkefE0BdgPiG4JEvEl6zEqcQMaLvi9fcxBljNWHzLbBuMeh2PV1Kx8OAi3mkjwuFNvq 5w0JyKjDUzzS0F7uxTjUTydDPfc+UPbpQ4qA5lBsExRA3K7zWAeki4U0bCY7eFQzjOm4 kDpCTky2ghenyth/NyPFpSr0EqP+JjN5XEvX8iR6JnXcWA6aCLgRE+GSJt5VDSl+9+v3 O4cOs1h27JPiqoGrdNxYzy6izLW0WerTmuB6SRuErWrT2pGgj6/qwHgT2VDXpVnIAlVt DBvQ== ARC-Authentication-Results: i=1; mx.google.com; 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id a9si9789704edk.466.2020.03.23.07.30.02; Mon, 23 Mar 2020 07:30:03 -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; 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DCBCA68B703; Mon, 23 Mar 2020 16:30:01 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id CA36468B679 for ; Mon, 23 Mar 2020 16:29:54 +0200 (EET) IronPort-SDR: jV2lTbQIpO9bUdf9JDhf5zItqMl+vPfCUEJWAt3omXNUIqMJw9kRbe/3xd+UZu1SgtQg3rnJTL IOqv7iDVZ0HA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Mar 2020 07:29:52 -0700 IronPort-SDR: cucs5H246pdPqS+8szWNixhU+eKd7HtjSWfMikPVtHoB6uH9tXMNq7QsuPPZ+55ACy8ETT1uQb 7C7MAvAN+Taw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,296,1580803200"; d="scan'208";a="445828950" Received: from icl-dev.sh.intel.com ([10.239.158.73]) by fmsmga005.fm.intel.com with ESMTP; 23 Mar 2020 07:29:51 -0700 From: Linjie Fu To: ffmpeg-devel@ffmpeg.org Date: Mon, 23 Mar 2020 22:24:16 +0800 Message-Id: <1584973456-32021-1-git-send-email-linjie.fu@intel.com> X-Mailer: git-send-email 2.7.4 Subject: [FFmpeg-devel] [PATCH 2/3] lavc/vaapi_encode: add tile slice encoding support 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 Cc: Linjie Fu MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: z9hveICHNaoU Content-Length: 12406 Add functions to initialize tile slice structure and make tile slice: - vaapi_encode_init_tile_slice_structure - vaapi_encode_make_tile_slice Tile slice is not allowed to cross the boundary of a tile due to the constraints of media-driver. Currently adding support for one slice per tile. N x N tile encoding is supposed to be supported with the the capability of ARBITRARY_MACROBLOCKS slice structures. N X 1 tile encoding should also work in ARBITRARY_ROWS slice structure. Signed-off-by: Linjie Fu --- libavcodec/vaapi_encode.c | 127 +++++++++++++++++++++++++++++++++++++++++++--- libavcodec/vaapi_encode.h | 16 ++++++ 2 files changed, 135 insertions(+), 8 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 8b48379..16b157d 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -212,6 +212,33 @@ static int vaapi_encode_make_row_slice(AVCodecContext *avctx, return 0; } +static int vaapi_encode_make_tile_slice(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeSlice *slice; + int i, j, index; + + for (i = 0; i < ctx->tile_cols; i++) { + for (j = 0; j < ctx->tile_rows; j++) { + index = j * ctx->tile_cols + i; + slice = &pic->slices[index]; + slice->index = index; + + pic->slices[index].block_start = ctx->col_bd[i] + + ctx->row_bd[j] * ctx->slice_block_cols; + pic->slices[index].block_size = ctx->row_height[j] * ctx->col_width[i]; + + av_log(avctx, AV_LOG_DEBUG, "Slice %2d: (%2d, %2d) start at: %4d " + "width:%2d height:%2d (%d blocks).\n", index, ctx->col_bd[i], + ctx->row_bd[j], slice->block_start, ctx->col_width[i], + ctx->row_height[j], slice->block_size); + } + } + + return 0; +} + static int vaapi_encode_issue(AVCodecContext *avctx, VAAPIEncodePicture *pic) { @@ -401,7 +428,10 @@ static int vaapi_encode_issue(AVCodecContext *avctx, goto fail; } - vaapi_encode_make_row_slice(avctx, pic); + if (ctx->tile_rows && ctx->tile_cols) + vaapi_encode_make_tile_slice(avctx, pic); + else + vaapi_encode_make_row_slice(avctx, pic); } for (i = 0; i < pic->nb_slices; i++) { @@ -1883,11 +1913,75 @@ static av_cold int vaapi_encode_init_row_slice_structure(AVCodecContext *avctx, return 0; } +static av_cold int vaapi_encode_init_tile_slice_structure(AVCodecContext *avctx, + uint32_t slice_structure) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + int i, req_tiles; + + if (!(slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS || + (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS && ctx->tile_cols == 1))) { + av_log(avctx, AV_LOG_ERROR, "Supported slice structure (%#x) doesn't work for " + "current tile requirement.\n", slice_structure); + return AVERROR(EINVAL); + } + + if (ctx->tile_rows > ctx->slice_block_rows || + ctx->tile_cols > ctx->slice_block_cols) { + av_log(avctx, AV_LOG_WARNING, "Not enough block rows/cols (%d x %d) " + "for configured number of tile (%d x %d); ", + ctx->slice_block_rows, ctx->slice_block_cols, + ctx->tile_rows, ctx->tile_cols); + ctx->tile_rows = ctx->tile_rows > ctx->slice_block_rows ? + ctx->slice_block_rows : ctx->tile_rows; + ctx->tile_cols = ctx->tile_cols > ctx->slice_block_cols ? + ctx->slice_block_cols : ctx->tile_cols; + av_log(avctx, AV_LOG_WARNING, "using allowed maximum (%d x %d).\n", + ctx->tile_rows, ctx->tile_cols); + } + + req_tiles = ctx->tile_rows * ctx->tile_cols; + + // Tile slice is not allowed to cross the boundary of a tile due to + // the constraints of media-driver. Currently we support one slice + // per tile. This could be extended to multiple slices per tile. + if (avctx->slices != req_tiles) + av_log(avctx, AV_LOG_WARNING, "The number of requested slices " + "mismatches with configured number of tile (%d != %d); " + "using requested tile number for slice.\n", + avctx->slices, req_tiles); + + ctx->nb_slices = req_tiles; + + // Default in uniform spacing + // 6-3, 6-5 + for (i = 0; i < ctx->tile_cols; i++) { + ctx->col_width[i] = ( i + 1 ) * ctx->slice_block_cols / ctx->tile_cols - + i * ctx->slice_block_cols / ctx->tile_cols; + ctx->col_bd[i + 1] = ctx->col_bd[i] + ctx->col_width[i]; + } + // 6-4, 6-6 + for (i = 0; i < ctx->tile_rows; i++) { + ctx->row_height[i] = ( i + 1 ) * ctx->slice_block_rows / ctx->tile_rows - + i * ctx->slice_block_rows / ctx->tile_rows; + ctx->row_bd[i + 1] = ctx->row_bd[i] + ctx->row_height[i]; + } + + av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d x %d tile.\n", + ctx->tile_rows, ctx->tile_cols); + + return 0; +} + static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; - VAConfigAttrib attr[2] = { { VAConfigAttribEncMaxSlices }, - { VAConfigAttribEncSliceStructure } }; + VAConfigAttrib attr[3] = { { VAConfigAttribEncMaxSlices }, + { VAConfigAttribEncSliceStructure }, +#if VA_CHECK_VERSION(1, 1, 0) + { VAConfigAttribEncTileSupport }, +#endif + }; VAStatus vas; uint32_t max_slices, slice_structure; int ret; @@ -1905,7 +1999,7 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) ctx->slice_block_cols = (avctx->width + ctx->slice_block_width - 1) / ctx->slice_block_width; - if (avctx->slices <= 1) { + if (avctx->slices <= 1 && !ctx->tile_rows && !ctx->tile_cols) { ctx->nb_slices = 1; ctx->slice_size = ctx->slice_block_rows; return 0; @@ -1929,7 +2023,25 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) return AVERROR(EINVAL); } - ret = vaapi_encode_init_row_slice_structure(avctx, slice_structure); + if (ctx->tile_rows && ctx->tile_cols) { +#if VA_CHECK_VERSION(1, 1, 0) + uint32_t tile_support = attr[2].value; + if (tile_support == VA_ATTRIB_NOT_SUPPORTED) { + av_log(avctx, AV_LOG_ERROR, "Driver does not support encoding " + "pictures as multiple tiles.\n."); + return AVERROR(EINVAL); + } +#else + av_log(avctx, AV_LOG_ERROR, "Tile encoding option is " + "not supported with this VAAPI version.\n"); + return AVERROR(EINVAL); +#endif + } + + if (ctx->tile_rows && ctx->tile_cols) + ret = vaapi_encode_init_tile_slice_structure(avctx, slice_structure); + else + ret = vaapi_encode_init_row_slice_structure(avctx, slice_structure); if (ret < 0) return ret; @@ -1945,9 +2057,8 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) 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); + av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices.\n", + ctx->nb_slices); return 0; } diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index b9a3def..5da9a76 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -42,6 +42,10 @@ enum { MAX_PICTURE_REFERENCES = 2, MAX_REORDER_DELAY = 16, MAX_PARAM_BUFFER_SIZE = 1024, + // A.4.1: table A.6 allows at most 22 tile rows for any level. + MAX_TILE_ROWS = 22, + // A.4.1: table A.6 allows at most 20 tile columns for any level. + MAX_TILE_COLS = 20, }; enum { @@ -299,6 +303,18 @@ typedef struct VAAPIEncodeContext { int nb_slices; int slice_size; + // Tile encoding. + int tile_rows; + int tile_cols; + // Tile width of the i-th column. + int col_width[MAX_TILE_COLS]; + // Tile height of i-th row. + int row_height[MAX_TILE_ROWS]; + // Location of the i-th tile column boundary. + int col_bd[MAX_TILE_COLS + 1]; + // Location of the i-th tile row boundary. + int row_bd[MAX_TILE_ROWS + 1]; + // Frame type decision. int gop_size; int closed_gop; From patchwork Mon Mar 23 14:24:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Fu, Linjie" X-Patchwork-Id: 18369 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id B2C4A44B9C7 for ; Mon, 23 Mar 2020 16:30:27 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9780268B6FC; Mon, 23 Mar 2020 16:30:27 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5535B68B801 for ; Mon, 23 Mar 2020 16:30:20 +0200 (EET) IronPort-SDR: YMDjKdBDFPD21R8PyUQL+bhzp4K1FNQ50Ug3VDkAnY98Rh+s7YF06ze2DtZLPnqnQgnsWlpQQf eU3qe6LExVIQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Mar 2020 07:30:18 -0700 IronPort-SDR: +kgDMm9l8azHsV5b/yInAotIYQGXZ7Sew5W9W5X511zv7ErXlbwVGNSuWr8OU0c1C9H+NkUiqA Y8TR82eQAHzQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,296,1580803200"; d="scan'208";a="445829154" Received: from icl-dev.sh.intel.com ([10.239.158.73]) by fmsmga005.fm.intel.com with ESMTP; 23 Mar 2020 07:30:17 -0700 From: Linjie Fu To: ffmpeg-devel@ffmpeg.org Date: Mon, 23 Mar 2020 22:24:39 +0800 Message-Id: <1584973479-32167-1-git-send-email-linjie.fu@intel.com> X-Mailer: git-send-email 2.7.4 Subject: [FFmpeg-devel] [PATCH 3/3] lavc/vaapi_encode_h265: add h265 tile encoding support 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 Cc: Linjie Fu MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Default to enable uniform_spacing_flag. Guess level by the tile rows/cols. Supported for ICL+ platforms. Also add documentations. To encode with 4 rows 2 columns: ffmpeg ... -c:v hevc_vaapi -tile_rows 4 -tile_cols 2 ... Signed-off-by: Linjie Fu --- doc/encoders.texi | 8 ++++++++ libavcodec/vaapi_encode_h265.c | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index e23b6b3..2dc5cd4 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3091,6 +3091,14 @@ Include HDR metadata if the input frames have it messages). @end table +@item tile_rows +Selects how many rows of tiles to encode with. For example, 4 tile rows would +be requested by setting the tile_rows option to 4. + +@item tile_cols +Selects how many columns of tiles to encode with. For example, 5 tile columns +would be requested by setting the tile_cols option to 5. + @end table @item mjpeg_vaapi diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 97dc5a7..457e3d9 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -63,6 +63,9 @@ typedef struct VAAPIEncodeH265Context { int level; int sei; + int trows; + int tcols; + // Derived settings. int fixed_qp_idr; int fixed_qp_p; @@ -345,7 +348,7 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) level = ff_h265_guess_level(ptl, avctx->bit_rate, ctx->surface_width, ctx->surface_height, - ctx->nb_slices, 1, 1, + ctx->nb_slices, ctx->tile_rows, ctx->tile_cols, (ctx->b_per_p > 0) + 1); if (level) { av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name); @@ -558,6 +561,20 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) pps->pps_loop_filter_across_slices_enabled_flag = 1; + if (ctx->tile_rows && ctx->tile_cols) { + pps->tiles_enabled_flag = 1; + pps->uniform_spacing_flag = 1; + + pps->num_tile_rows_minus1 = ctx->tile_rows - 1; + pps->num_tile_columns_minus1 = ctx->tile_cols - 1; + + pps->loop_filter_across_tiles_enabled_flag = 1; + + for (i = 0; i <= pps->num_tile_rows_minus1; i++) + pps->row_height_minus1[i] = ctx->row_height[i] - 1; + for (i = 0; i <= pps->num_tile_columns_minus1; i++) + pps->column_width_minus1[i] = ctx->col_width[i] - 1; + } // Fill VAAPI parameter buffers. @@ -666,6 +683,13 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) }, }; + if (pps->tiles_enabled_flag) { + for (i = 0; i <= vpic->num_tile_rows_minus1; i++) + vpic->row_height_minus1[i] = pps->row_height_minus1[i]; + for (i = 0; i <= vpic->num_tile_columns_minus1; i++) + vpic->column_width_minus1[i] = pps->column_width_minus1[i]; + } + return 0; } @@ -1181,6 +1205,11 @@ static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx) if (priv->qp > 0) ctx->explicit_qp = priv->qp; + if (priv->trows && priv->tcols) { + ctx->tile_rows = priv->trows; + ctx->tile_cols = priv->tcols; + } + return ff_vaapi_encode_init(avctx); } @@ -1257,6 +1286,11 @@ static const AVOption vaapi_encode_h265_options[] = { { .i64 = SEI_MASTERING_DISPLAY | SEI_CONTENT_LIGHT_LEVEL }, INT_MIN, INT_MAX, FLAGS, "sei" }, + { "tile_rows", "Number of rows for tile encoding", + OFFSET(trows), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { "tile_cols", "Number of cols for tile encoding", + OFFSET(tcols), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { NULL }, };