diff mbox

[FFmpeg-devel] lavc/qsvenc: add Tiles encode support for HEVC

Message ID 1574740578-3098-1-git-send-email-linjie.fu@intel.com
State Accepted
Commit 8446318502bf21347a4867a5a1fcd8d9bfbd6a41
Headers show

Commit Message

Fu, Linjie Nov. 26, 2019, 3:56 a.m. UTC
Add -tile_rows and -tile_cols option to specify the number of tile rows
and columns for ICL+ (gen 11) platform.

A tile must wholly contain all the slices within it. Slices cannot cross
tile boundaries. So the slice number would be implicitly resized to the
max(nSlice, nTile).

Example:
    ffmpeg -v verbose -hwaccel qsv -init_hw_device qsv=hw
    -filter_hw_device hw -f rawvideo -s:v 1920x1080 -i ./input.nv12 -vf
    format=nv12,hwupload=extra_hw_frames=64 -c:v hevc_qsv -tile_rows 2
    -tile_cols 2 -slices 4 -y output.h265

Also dump the actual quantity of encoded tiled rows and columns in run
time.

Fix the enhancement #8400.

Signed-off-by: Linjie Fu <linjie.fu@intel.com>
---
 libavcodec/qsvenc.c      | 32 +++++++++++++++++++++++++++++++-
 libavcodec/qsvenc.h      |  7 +++++++
 libavcodec/qsvenc_hevc.c |  3 +++
 3 files changed, 41 insertions(+), 1 deletion(-)

Comments

Fu, Linjie Nov. 28, 2019, 1:34 a.m. UTC | #1
Hi,

> -----Original Message-----
> From: Fu, Linjie <linjie.fu@intel.com>
> Sent: Tuesday, November 26, 2019 11:56
> To: ffmpeg-devel@ffmpeg.org
> Cc: Fu, Linjie <linjie.fu@intel.com>
> Subject: [PATCH] lavc/qsvenc: add Tiles encode support for HEVC
> 
> Add -tile_rows and -tile_cols option to specify the number of tile rows
> and columns for ICL+ (gen 11) platform.
> 
> A tile must wholly contain all the slices within it. Slices cannot cross
> tile boundaries. So the slice number would be implicitly resized to the
> max(nSlice, nTile).
> 
> Example:
>     ffmpeg -v verbose -hwaccel qsv -init_hw_device qsv=hw
>     -filter_hw_device hw -f rawvideo -s:v 1920x1080 -i ./input.nv12 -vf
>     format=nv12,hwupload=extra_hw_frames=64 -c:v hevc_qsv -tile_rows 2
>     -tile_cols 2 -slices 4 -y output.h265
> 
> Also dump the actual quantity of encoded tiled rows and columns in run
> time.
> 
> Fix the enhancement #8400.
> 
> Signed-off-by: Linjie Fu <linjie.fu@intel.com>
> ---
>  libavcodec/qsvenc.c      | 32 +++++++++++++++++++++++++++++++-
>  libavcodec/qsvenc.h      |  7 +++++++
>  libavcodec/qsvenc_hevc.c |  3 +++
>  3 files changed, 41 insertions(+), 1 deletion(-)
> 
> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> index e176d57..64814fc 100644
> --- a/libavcodec/qsvenc.c
> +++ b/libavcodec/qsvenc.c
> @@ -139,6 +139,9 @@ static void dump_video_param(AVCodecContext
> *avctx, QSVEncContext *q,
>  #if QSV_HAVE_CO3
>      mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
>  #endif
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    mfxExtHEVCTiles *exthevctiles = (mfxExtHEVCTiles *)coding_opts[3 +
> QSV_HAVE_CO_VPS];
> +#endif
> 
>      av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",
>             print_profile(info->CodecProfile), info->CodecLevel);
> @@ -204,6 +207,12 @@ static void dump_video_param(AVCodecContext
> *avctx, QSVEncContext *q,
>      av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n",
>             print_threestate(co->RateDistortionOpt));
> 
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    if (avctx->codec_id == AV_CODEC_ID_HEVC)
> +        av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16";
> NumTileRows: %"PRIu16"\n",
> +               exthevctiles->NumTileColumns, exthevctiles->NumTileRows);
> +#endif
> +
>  #if QSV_HAVE_CO2
>      av_log(avctx, AV_LOG_VERBOSE,
>             "RecoveryPointSEI: %s IntRefType: %"PRIu16";
> IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n",
> @@ -771,6 +780,16 @@ FF_ENABLE_DEPRECATION_WARNINGS
>      }
>  #endif
> 
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    if (avctx->codec_id == AV_CODEC_ID_HEVC) {
> +        q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES;
> +        q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles);
> +        q->exthevctiles.NumTileColumns  = q->tile_cols;
> +        q->exthevctiles.NumTileRows     = q->tile_rows;
> +        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer
> *)&q->exthevctiles;
> +    }
> +#endif
> +
>      if (!check_enc_param(avctx,q)) {
>          av_log(avctx, AV_LOG_ERROR,
>                 "some encoding parameters are not supported by the QSV "
> @@ -887,7 +906,14 @@ static int
> qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
>      };
>  #endif
> 
> -    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 +
> QSV_HAVE_CO_VPS];
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    mfxExtHEVCTiles hevc_tile_buf = {
> +         .Header.BufferId = MFX_EXTBUFF_HEVC_TILES,
> +         .Header.BufferSz = sizeof(hevc_tile_buf),
> +    };
> +#endif
> +
> +    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 +
> QSV_HAVE_CO_VPS + QSV_HAVE_EXT_HEVC_TILES];
> 
>      int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
>      int ret, ext_buf_num = 0, extradata_offset = 0;
> @@ -905,6 +931,10 @@ static int
> qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
>      if (q->hevc_vps)
>          ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata_vps;
>  #endif
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    if (avctx->codec_id == AV_CODEC_ID_HEVC)
> +        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&hevc_tile_buf;
> +#endif
> 
>      q->param.ExtParam    = ext_buffers;
>      q->param.NumExtParam = ext_buf_num;
> diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
> index ee35582..6609171 100644
> --- a/libavcodec/qsvenc.h
> +++ b/libavcodec/qsvenc.h
> @@ -38,6 +38,7 @@
>  #define QSV_HAVE_CO3 QSV_VERSION_ATLEAST(1, 11)
>  #define QSV_HAVE_CO_VPS  QSV_VERSION_ATLEAST(1, 17)
> 
> +#define QSV_HAVE_EXT_HEVC_TILES QSV_VERSION_ATLEAST(1, 13)
>  #define QSV_HAVE_EXT_VP9_PARAM QSV_VERSION_ATLEAST(1, 26)
> 
>  #define QSV_HAVE_TRELLIS QSV_VERSION_ATLEAST(1, 8)
> @@ -124,6 +125,9 @@ typedef struct QSVEncContext {
>      mfxExtMultiFrameParam   extmfp;
>      mfxExtMultiFrameControl extmfc;
>  #endif
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    mfxExtHEVCTiles exthevctiles;
> +#endif
>  #if QSV_HAVE_EXT_VP9_PARAM
>      mfxExtVP9Param  extvp9param;
>  #endif
> @@ -161,6 +165,9 @@ typedef struct QSVEncContext {
>      int max_frame_size;
>      int max_slice_size;
> 
> +    int tile_cols;
> +    int tile_rows;
> +
>      int aud;
> 
>      int single_sei_nal_unit;
> diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c
> index da64b4c..27e2232 100644
> --- a/libavcodec/qsvenc_hevc.c
> +++ b/libavcodec/qsvenc_hevc.c
> @@ -243,6 +243,9 @@ static const AVOption options[] = {
> 
>      { "gpb", "1: GPB (generalized P/B frame); 0: regular P frame",
> OFFSET(qsv.gpb), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE},
> 
> +    { "tile_cols",  "Number of columns for tiled encoding",
> OFFSET(qsv.tile_cols),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE },
> +    { "tile_rows",  "Number of rows for tiled encoding",
> OFFSET(qsv.tile_rows),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE },
> +
>      { NULL },
>  };
> 
> --
> 2.7.4

The issue that tile encoding fails with default slice number(1) has been fixed by:
https://github.com/Intel-Media-SDK/MediaSDK/commit/f8ba11a5b7d61422b117bec2b5b88e4a22bbd294
and merged into MediaSDK master.

Hence this feature doesn't have blocking issues any more.
Ping for comments, thanks.

- linjie
mypopy@gmail.com Nov. 29, 2019, 5:02 a.m. UTC | #2
On Tue, Nov 26, 2019 at 12:04 PM Linjie Fu <linjie.fu@intel.com> wrote:
>
> Add -tile_rows and -tile_cols option to specify the number of tile rows
> and columns for ICL+ (gen 11) platform.
>
> A tile must wholly contain all the slices within it. Slices cannot cross
> tile boundaries. So the slice number would be implicitly resized to the
> max(nSlice, nTile).
>
> Example:
>     ffmpeg -v verbose -hwaccel qsv -init_hw_device qsv=hw
>     -filter_hw_device hw -f rawvideo -s:v 1920x1080 -i ./input.nv12 -vf
>     format=nv12,hwupload=extra_hw_frames=64 -c:v hevc_qsv -tile_rows 2
>     -tile_cols 2 -slices 4 -y output.h265
>
> Also dump the actual quantity of encoded tiled rows and columns in run
> time.
>
> Fix the enhancement #8400.
>
> Signed-off-by: Linjie Fu <linjie.fu@intel.com>
> ---
>  libavcodec/qsvenc.c      | 32 +++++++++++++++++++++++++++++++-
>  libavcodec/qsvenc.h      |  7 +++++++
>  libavcodec/qsvenc_hevc.c |  3 +++
>  3 files changed, 41 insertions(+), 1 deletion(-)
>
> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> index e176d57..64814fc 100644
> --- a/libavcodec/qsvenc.c
> +++ b/libavcodec/qsvenc.c
> @@ -139,6 +139,9 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
>  #if QSV_HAVE_CO3
>      mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
>  #endif
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    mfxExtHEVCTiles *exthevctiles = (mfxExtHEVCTiles *)coding_opts[3 + QSV_HAVE_CO_VPS];
> +#endif
>
>      av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",
>             print_profile(info->CodecProfile), info->CodecLevel);
> @@ -204,6 +207,12 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
>      av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n",
>             print_threestate(co->RateDistortionOpt));
>
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    if (avctx->codec_id == AV_CODEC_ID_HEVC)
> +        av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16"; NumTileRows: %"PRIu16"\n",
> +               exthevctiles->NumTileColumns, exthevctiles->NumTileRows);
> +#endif
> +
>  #if QSV_HAVE_CO2
>      av_log(avctx, AV_LOG_VERBOSE,
>             "RecoveryPointSEI: %s IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n",
> @@ -771,6 +780,16 @@ FF_ENABLE_DEPRECATION_WARNINGS
>      }
>  #endif
>
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    if (avctx->codec_id == AV_CODEC_ID_HEVC) {
> +        q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES;
> +        q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles);
> +        q->exthevctiles.NumTileColumns  = q->tile_cols;
> +        q->exthevctiles.NumTileRows     = q->tile_rows;
Is it have any other limition for the number of tile columns/rows ?
> +        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->exthevctiles;
> +    }
> +#endif
> +
>      if (!check_enc_param(avctx,q)) {
>          av_log(avctx, AV_LOG_ERROR,
>                 "some encoding parameters are not supported by the QSV "
> @@ -887,7 +906,14 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
>      };
>  #endif
>
> -    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS];
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    mfxExtHEVCTiles hevc_tile_buf = {
> +         .Header.BufferId = MFX_EXTBUFF_HEVC_TILES,
> +         .Header.BufferSz = sizeof(hevc_tile_buf),
> +    };
> +#endif
> +
> +    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS + QSV_HAVE_EXT_HEVC_TILES];
>
>      int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
>      int ret, ext_buf_num = 0, extradata_offset = 0;
> @@ -905,6 +931,10 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
>      if (q->hevc_vps)
>          ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata_vps;
>  #endif
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    if (avctx->codec_id == AV_CODEC_ID_HEVC)
> +        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&hevc_tile_buf;
> +#endif
>
>      q->param.ExtParam    = ext_buffers;
>      q->param.NumExtParam = ext_buf_num;
> diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
> index ee35582..6609171 100644
> --- a/libavcodec/qsvenc.h
> +++ b/libavcodec/qsvenc.h
> @@ -38,6 +38,7 @@
>  #define QSV_HAVE_CO3 QSV_VERSION_ATLEAST(1, 11)
>  #define QSV_HAVE_CO_VPS  QSV_VERSION_ATLEAST(1, 17)
>
> +#define QSV_HAVE_EXT_HEVC_TILES QSV_VERSION_ATLEAST(1, 13)
>  #define QSV_HAVE_EXT_VP9_PARAM QSV_VERSION_ATLEAST(1, 26)
>
>  #define QSV_HAVE_TRELLIS QSV_VERSION_ATLEAST(1, 8)
> @@ -124,6 +125,9 @@ typedef struct QSVEncContext {
>      mfxExtMultiFrameParam   extmfp;
>      mfxExtMultiFrameControl extmfc;
>  #endif
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    mfxExtHEVCTiles exthevctiles;
> +#endif
>  #if QSV_HAVE_EXT_VP9_PARAM
>      mfxExtVP9Param  extvp9param;
>  #endif
> @@ -161,6 +165,9 @@ typedef struct QSVEncContext {
>      int max_frame_size;
>      int max_slice_size;
>
> +    int tile_cols;
> +    int tile_rows;
> +
>      int aud;
>
>      int single_sei_nal_unit;
> diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c
> index da64b4c..27e2232 100644
> --- a/libavcodec/qsvenc_hevc.c
> +++ b/libavcodec/qsvenc_hevc.c
> @@ -243,6 +243,9 @@ static const AVOption options[] = {
>
>      { "gpb", "1: GPB (generalized P/B frame); 0: regular P frame", OFFSET(qsv.gpb), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE},
>
> +    { "tile_cols",  "Number of columns for tiled encoding",   OFFSET(qsv.tile_cols),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE },
> +    { "tile_rows",  "Number of rows for tiled encoding",      OFFSET(qsv.tile_rows),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE },
> +
>      { NULL },
>  };
>
> --
> 2.7.4
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Zhong Li Nov. 29, 2019, 5:13 a.m. UTC | #3
Linjie Fu <linjie.fu@intel.com> 于2019年11月26日周二 下午12:04写道:
>
> Add -tile_rows and -tile_cols option to specify the number of tile rows
> and columns for ICL+ (gen 11) platform.
>
> A tile must wholly contain all the slices within it. Slices cannot cross
> tile boundaries. So the slice number would be implicitly resized to the
> max(nSlice, nTile).

I would like to the check in the code too, instead of  just commit message.

> Example:
>     ffmpeg -v verbose -hwaccel qsv -init_hw_device qsv=hw
>     -filter_hw_device hw -f rawvideo -s:v 1920x1080 -i ./input.nv12 -vf
>     format=nv12,hwupload=extra_hw_frames=64 -c:v hevc_qsv -tile_rows 2
>     -tile_cols 2 -slices 4 -y output.h265
>
> Also dump the actual quantity of encoded tiled rows and columns in run
> time.
>
> Fix the enhancement #8400.
>
> Signed-off-by: Linjie Fu <linjie.fu@intel.com>
> ---
>  libavcodec/qsvenc.c      | 32 +++++++++++++++++++++++++++++++-
>  libavcodec/qsvenc.h      |  7 +++++++
>  libavcodec/qsvenc_hevc.c |  3 +++
>  3 files changed, 41 insertions(+), 1 deletion(-)
>
> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> index e176d57..64814fc 100644
> --- a/libavcodec/qsvenc.c
> +++ b/libavcodec/qsvenc.c
> @@ -139,6 +139,9 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
>  #if QSV_HAVE_CO3
>      mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
>  #endif
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    mfxExtHEVCTiles *exthevctiles = (mfxExtHEVCTiles *)coding_opts[3 + QSV_HAVE_CO_VPS];

Should change QSV_HAVE_CO_VPS to QSV_HAVE_EXT_HEVC_TILES?

> +#endif
>
>      av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",
>             print_profile(info->CodecProfile), info->CodecLevel);
> @@ -204,6 +207,12 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
>      av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n",
>             print_threestate(co->RateDistortionOpt));
>
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    if (avctx->codec_id == AV_CODEC_ID_HEVC)
> +        av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16"; NumTileRows: %"PRIu16"\n",
> +               exthevctiles->NumTileColumns, exthevctiles->NumTileRows);
> +#endif
> +
>  #if QSV_HAVE_CO2
>      av_log(avctx, AV_LOG_VERBOSE,
>             "RecoveryPointSEI: %s IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n",
> @@ -771,6 +780,16 @@ FF_ENABLE_DEPRECATION_WARNINGS
>      }
>  #endif
>
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    if (avctx->codec_id == AV_CODEC_ID_HEVC) {
> +        q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES;
> +        q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles);
> +        q->exthevctiles.NumTileColumns  = q->tile_cols;
> +        q->exthevctiles.NumTileRows     = q->tile_rows;
> +        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->exthevctiles;
> +    }
> +#endif
> +
>      if (!check_enc_param(avctx,q)) {
>          av_log(avctx, AV_LOG_ERROR,
>                 "some encoding parameters are not supported by the QSV "
> @@ -887,7 +906,14 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
>      };
>  #endif
>
> -    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS];
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    mfxExtHEVCTiles hevc_tile_buf = {
> +         .Header.BufferId = MFX_EXTBUFF_HEVC_TILES,
> +         .Header.BufferSz = sizeof(hevc_tile_buf),
> +    };
> +#endif
> +
> +    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS + QSV_HAVE_EXT_HEVC_TILES];
>
>      int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
>      int ret, ext_buf_num = 0, extradata_offset = 0;
> @@ -905,6 +931,10 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
>      if (q->hevc_vps)
>          ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata_vps;
>  #endif
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    if (avctx->codec_id == AV_CODEC_ID_HEVC)
> +        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&hevc_tile_buf;
> +#endif
>
>      q->param.ExtParam    = ext_buffers;
>      q->param.NumExtParam = ext_buf_num;
> diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
> index ee35582..6609171 100644
> --- a/libavcodec/qsvenc.h
> +++ b/libavcodec/qsvenc.h
> @@ -38,6 +38,7 @@
>  #define QSV_HAVE_CO3 QSV_VERSION_ATLEAST(1, 11)
>  #define QSV_HAVE_CO_VPS  QSV_VERSION_ATLEAST(1, 17)
>
> +#define QSV_HAVE_EXT_HEVC_TILES QSV_VERSION_ATLEAST(1, 13)
>  #define QSV_HAVE_EXT_VP9_PARAM QSV_VERSION_ATLEAST(1, 26)
>
>  #define QSV_HAVE_TRELLIS QSV_VERSION_ATLEAST(1, 8)
> @@ -124,6 +125,9 @@ typedef struct QSVEncContext {
>      mfxExtMultiFrameParam   extmfp;
>      mfxExtMultiFrameControl extmfc;
>  #endif
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    mfxExtHEVCTiles exthevctiles;
> +#endif
>  #if QSV_HAVE_EXT_VP9_PARAM
>      mfxExtVP9Param  extvp9param;
>  #endif
> @@ -161,6 +165,9 @@ typedef struct QSVEncContext {
>      int max_frame_size;
>      int max_slice_size;
>
> +    int tile_cols;
> +    int tile_rows;
> +
>      int aud;
>
>      int single_sei_nal_unit;
> diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c
> index da64b4c..27e2232 100644
> --- a/libavcodec/qsvenc_hevc.c
> +++ b/libavcodec/qsvenc_hevc.c
> @@ -243,6 +243,9 @@ static const AVOption options[] = {
>
>      { "gpb", "1: GPB (generalized P/B frame); 0: regular P frame", OFFSET(qsv.gpb), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE},
>
> +    { "tile_cols",  "Number of columns for tiled encoding",   OFFSET(qsv.tile_cols),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE },

should better to keep consist with other codecs such as vp9/av1 to set
the name as tile_columns.

And I note the value is log2 in these codecs.

> +    { "tile_rows",  "Number of rows for tiled encoding",      OFFSET(qsv.tile_rows),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE },
> +
>      { NULL },
>  };
>
> --
> 2.7.4

One problem is that I have no ICL to test the patch.
Fu, Linjie Nov. 29, 2019, 5:44 a.m. UTC | #4
> -----Original Message-----

> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of

> mypopy@gmail.com

> Sent: Friday, November 29, 2019 13:03

> To: FFmpeg development discussions and patches <ffmpeg-

> devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] [PATCH] lavc/qsvenc: add Tiles encode support

> for HEVC

> 

> On Tue, Nov 26, 2019 at 12:04 PM Linjie Fu <linjie.fu@intel.com> wrote:

> >

> > Add -tile_rows and -tile_cols option to specify the number of tile rows

> > and columns for ICL+ (gen 11) platform.

> >

> > A tile must wholly contain all the slices within it. Slices cannot cross

> > tile boundaries. So the slice number would be implicitly resized to the

> > max(nSlice, nTile).

> >

> > Example:

> >     ffmpeg -v verbose -hwaccel qsv -init_hw_device qsv=hw

> >     -filter_hw_device hw -f rawvideo -s:v 1920x1080 -i ./input.nv12 -vf

> >     format=nv12,hwupload=extra_hw_frames=64 -c:v hevc_qsv -tile_rows 2

> >     -tile_cols 2 -slices 4 -y output.h265

> >

> > Also dump the actual quantity of encoded tiled rows and columns in run

> > time.

> >

> > Fix the enhancement #8400.

> >

> > Signed-off-by: Linjie Fu <linjie.fu@intel.com>

> > ---

> >  libavcodec/qsvenc.c      | 32 +++++++++++++++++++++++++++++++-

> >  libavcodec/qsvenc.h      |  7 +++++++

> >  libavcodec/qsvenc_hevc.c |  3 +++

> >  3 files changed, 41 insertions(+), 1 deletion(-)

> >

> > diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c

> > index e176d57..64814fc 100644

> > --- a/libavcodec/qsvenc.c

> > +++ b/libavcodec/qsvenc.c

> > @@ -139,6 +139,9 @@ static void dump_video_param(AVCodecContext

> *avctx, QSVEncContext *q,

> >  #if QSV_HAVE_CO3

> >      mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];

> >  #endif

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    mfxExtHEVCTiles *exthevctiles = (mfxExtHEVCTiles *)coding_opts[3 +

> QSV_HAVE_CO_VPS];

> > +#endif

> >

> >      av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",

> >             print_profile(info->CodecProfile), info->CodecLevel);

> > @@ -204,6 +207,12 @@ static void dump_video_param(AVCodecContext

> *avctx, QSVEncContext *q,

> >      av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n",

> >             print_threestate(co->RateDistortionOpt));

> >

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    if (avctx->codec_id == AV_CODEC_ID_HEVC)

> > +        av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16";

> NumTileRows: %"PRIu16"\n",

> > +               exthevctiles->NumTileColumns, exthevctiles->NumTileRows);

> > +#endif

> > +

> >  #if QSV_HAVE_CO2

> >      av_log(avctx, AV_LOG_VERBOSE,

> >             "RecoveryPointSEI: %s IntRefType: %"PRIu16";

> IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n",

> > @@ -771,6 +780,16 @@ FF_ENABLE_DEPRECATION_WARNINGS

> >      }

> >  #endif

> >

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    if (avctx->codec_id == AV_CODEC_ID_HEVC) {

> > +        q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES;

> > +        q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles);

> > +        q->exthevctiles.NumTileColumns  = q->tile_cols;

> > +        q->exthevctiles.NumTileRows     = q->tile_rows;

> Is it have any other limition for the number of tile columns/rows ?


It depends on the  total number of row/column blocks and the work mode of encoder(VDEnc or VMEPAK).
The limitation varies:
https://github.com/Intel-Media-SDK/MediaSDK/blob/5a84af5fa61823a84f32e4b26d864730a927f48c/_studio/mfx_lib/encode_hw/h265/src/mfx_h265_encode_hw_par.cpp#L524

Hence I dumped the returned MFX_EXTBUFF_HEVC_TILES buffer to see the truly supported numbers
of Columns and Rows.

If the setting of row or col is out of range, this would help to inform user.

Thanks,

- linjie
Fu, Linjie Nov. 29, 2019, 6:42 a.m. UTC | #5
> -----Original Message-----

> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of

> Zhong Li

> Sent: Friday, November 29, 2019 13:13

> To: FFmpeg development discussions and patches <ffmpeg-

> devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] [PATCH] lavc/qsvenc: add Tiles encode support

> for HEVC

> 

> Linjie Fu <linjie.fu@intel.com> 于2019年11月26日周二 下午12:04写道:

> >

> > Add -tile_rows and -tile_cols option to specify the number of tile rows

> > and columns for ICL+ (gen 11) platform.

> >

> > A tile must wholly contain all the slices within it. Slices cannot cross

> > tile boundaries. So the slice number would be implicitly resized to the

> > max(nSlice, nTile).

> 

> I would like to the check in the code too, instead of  just commit message.


Thanks, code link in MSDK should have been attached too:
https://github.com/Intel-Media-SDK/MediaSDK/blob/5a84af5fa61823a84f32e4b26d864730a927f48c/_studio/mfx_lib/encode_hw/h265/src/mfx_h265_encode_hw_par.cpp#L503

This is merged in:
https://github.com/Intel-Media-SDK/MediaSDK/commit/f8ba11a5b7d61422b117bec2b5b88e4a22bbd294

> 

> > Example:

> >     ffmpeg -v verbose -hwaccel qsv -init_hw_device qsv=hw

> >     -filter_hw_device hw -f rawvideo -s:v 1920x1080 -i ./input.nv12 -vf

> >     format=nv12,hwupload=extra_hw_frames=64 -c:v hevc_qsv -tile_rows 2

> >     -tile_cols 2 -slices 4 -y output.h265

> >

> > Also dump the actual quantity of encoded tiled rows and columns in run

> > time.

> >

> > Fix the enhancement #8400.

> >

> > Signed-off-by: Linjie Fu <linjie.fu@intel.com>

> > ---

> >  libavcodec/qsvenc.c      | 32 +++++++++++++++++++++++++++++++-

> >  libavcodec/qsvenc.h      |  7 +++++++

> >  libavcodec/qsvenc_hevc.c |  3 +++

> >  3 files changed, 41 insertions(+), 1 deletion(-)

> >

> > diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c

> > index e176d57..64814fc 100644

> > --- a/libavcodec/qsvenc.c

> > +++ b/libavcodec/qsvenc.c

> > @@ -139,6 +139,9 @@ static void dump_video_param(AVCodecContext

> *avctx, QSVEncContext *q,

> >  #if QSV_HAVE_CO3

> >      mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];

> >  #endif

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    mfxExtHEVCTiles *exthevctiles = (mfxExtHEVCTiles *)coding_opts[3 +

> QSV_HAVE_CO_VPS];

> 

> Should change QSV_HAVE_CO_VPS to QSV_HAVE_EXT_HEVC_TILES?


There is possibility(MSDK version between 1.13 and 1.17) that MSDK has
MFX_EXTBUFF_HEVC_TILES buffer but has no MFX_EXT_BUFF_CODING_OPTION_VPS
buffer.

ext_buffers[]:
BUF_CO | BUF_CO2 | BUF_CO3 | BUF_VPS | BUF_TILE |...

Hence I'd like to check QSV_HAVE_CO_VPS to get the exact address of BUF_TILE
to dump the truly set values.

> 

> > +#endif

> >

> >      av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",

> >             print_profile(info->CodecProfile), info->CodecLevel);

> > @@ -204,6 +207,12 @@ static void dump_video_param(AVCodecContext

> *avctx, QSVEncContext *q,

> >      av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n",

> >             print_threestate(co->RateDistortionOpt));

> >

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    if (avctx->codec_id == AV_CODEC_ID_HEVC)

> > +        av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16";

> NumTileRows: %"PRIu16"\n",

> > +               exthevctiles->NumTileColumns, exthevctiles->NumTileRows);

> > +#endif

> > +

> >  #if QSV_HAVE_CO2

> >      av_log(avctx, AV_LOG_VERBOSE,

> >             "RecoveryPointSEI: %s IntRefType: %"PRIu16";

> IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n",

> > @@ -771,6 +780,16 @@ FF_ENABLE_DEPRECATION_WARNINGS

> >      }

> >  #endif

> >

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    if (avctx->codec_id == AV_CODEC_ID_HEVC) {

> > +        q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES;

> > +        q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles);

> > +        q->exthevctiles.NumTileColumns  = q->tile_cols;

> > +        q->exthevctiles.NumTileRows     = q->tile_rows;

> > +        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer

> *)&q->exthevctiles;

> > +    }

> > +#endif

> > +

> >      if (!check_enc_param(avctx,q)) {

> >          av_log(avctx, AV_LOG_ERROR,

> >                 "some encoding parameters are not supported by the QSV "

> > @@ -887,7 +906,14 @@ static int

> qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)

> >      };

> >  #endif

> >

> > -    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 +

> QSV_HAVE_CO_VPS];

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    mfxExtHEVCTiles hevc_tile_buf = {

> > +         .Header.BufferId = MFX_EXTBUFF_HEVC_TILES,

> > +         .Header.BufferSz = sizeof(hevc_tile_buf),

> > +    };

> > +#endif

> > +

> > +    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 +

> QSV_HAVE_CO_VPS + QSV_HAVE_EXT_HEVC_TILES];

> >

> >      int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;

> >      int ret, ext_buf_num = 0, extradata_offset = 0;

> > @@ -905,6 +931,10 @@ static int

> qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)

> >      if (q->hevc_vps)

> >          ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata_vps;

> >  #endif

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    if (avctx->codec_id == AV_CODEC_ID_HEVC)

> > +        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&hevc_tile_buf;

> > +#endif

> >

> >      q->param.ExtParam    = ext_buffers;

> >      q->param.NumExtParam = ext_buf_num;

> > diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h

> > index ee35582..6609171 100644

> > --- a/libavcodec/qsvenc.h

> > +++ b/libavcodec/qsvenc.h

> > @@ -38,6 +38,7 @@

> >  #define QSV_HAVE_CO3 QSV_VERSION_ATLEAST(1, 11)

> >  #define QSV_HAVE_CO_VPS  QSV_VERSION_ATLEAST(1, 17)

> >

> > +#define QSV_HAVE_EXT_HEVC_TILES QSV_VERSION_ATLEAST(1, 13)

> >  #define QSV_HAVE_EXT_VP9_PARAM QSV_VERSION_ATLEAST(1, 26)

> >

> >  #define QSV_HAVE_TRELLIS QSV_VERSION_ATLEAST(1, 8)

> > @@ -124,6 +125,9 @@ typedef struct QSVEncContext {

> >      mfxExtMultiFrameParam   extmfp;

> >      mfxExtMultiFrameControl extmfc;

> >  #endif

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    mfxExtHEVCTiles exthevctiles;

> > +#endif

> >  #if QSV_HAVE_EXT_VP9_PARAM

> >      mfxExtVP9Param  extvp9param;

> >  #endif

> > @@ -161,6 +165,9 @@ typedef struct QSVEncContext {

> >      int max_frame_size;

> >      int max_slice_size;

> >

> > +    int tile_cols;

> > +    int tile_rows;

> > +

> >      int aud;

> >

> >      int single_sei_nal_unit;

> > diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c

> > index da64b4c..27e2232 100644

> > --- a/libavcodec/qsvenc_hevc.c

> > +++ b/libavcodec/qsvenc_hevc.c

> > @@ -243,6 +243,9 @@ static const AVOption options[] = {

> >

> >      { "gpb", "1: GPB (generalized P/B frame); 0: regular P frame",

> OFFSET(qsv.gpb), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE},

> >

> > +    { "tile_cols",  "Number of columns for tiled encoding",

> OFFSET(qsv.tile_cols),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE },

> 

> should better to keep consist with other codecs such as vp9/av1 to set

> the name as tile_columns.

> 

> And I note the value is log2 in these codecs.


Yes, I've noticed the name and values in log2 formats. 
BTW, MSDK allows Tile structures (such as 3x3 Tiles) instead of only 2^.. Tiles,
would it be better to use log2 format to set the rows/columns?

> > +    { "tile_rows",  "Number of rows for tiled encoding",

> OFFSET(qsv.tile_rows),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE },

> > +

> >      { NULL },

> >  };

> >

> > --

> > 2.7.4

> 

> One problem is that I have no ICL to test the patch.


Um...
It's true that's a problem.

Thanks,

- linjie
Linjie Fu Dec. 7, 2019, 6:28 a.m. UTC | #6
Hi,

On Fri, Nov 29, 2019 at 2:42 PM Fu, Linjie <linjie.fu@intel.com> wrote:

> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > Zhong Li
> > Sent: Friday, November 29, 2019 13:13
> > To: FFmpeg development discussions and patches <ffmpeg-
> > devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [PATCH] lavc/qsvenc: add Tiles encode support
> > for HEVC
> >
> > Linjie Fu <linjie.fu@intel.com> 于2019年11月26日周二 下午12:04写道:
> > >
> > > Add -tile_rows and -tile_cols option to specify the number of tile rows
> > > and columns for ICL+ (gen 11) platform.
> > >
> > > A tile must wholly contain all the slices within it. Slices cannot
> cross
> > > tile boundaries. So the slice number would be implicitly resized to the
> > > max(nSlice, nTile).
> >
> > I would like to the check in the code too, instead of  just commit
> message.
>
> Thanks, code link in MSDK should have been attached too:
>
> https://github.com/Intel-Media-SDK/MediaSDK/blob/5a84af5fa61823a84f32e4b26d864730a927f48c/_studio/mfx_lib/encode_hw/h265/src/mfx_h265_encode_hw_par.cpp#L503
>
> This is merged in:
>
> https://github.com/Intel-Media-SDK/MediaSDK/commit/f8ba11a5b7d61422b117bec2b5b88e4a22bbd294
>
> >
> > > Example:
> > >     ffmpeg -v verbose -hwaccel qsv -init_hw_device qsv=hw
> > >     -filter_hw_device hw -f rawvideo -s:v 1920x1080 -i ./input.nv12 -vf
> > >     format=nv12,hwupload=extra_hw_frames=64 -c:v hevc_qsv -tile_rows 2
> > >     -tile_cols 2 -slices 4 -y output.h265
> > >
> > > Also dump the actual quantity of encoded tiled rows and columns in run
> > > time.
> > >
> > > Fix the enhancement #8400.
> > >
> > > Signed-off-by: Linjie Fu <linjie.fu@intel.com>
> > > ---
> > >  libavcodec/qsvenc.c      | 32 +++++++++++++++++++++++++++++++-
> > >  libavcodec/qsvenc.h      |  7 +++++++
> > >  libavcodec/qsvenc_hevc.c |  3 +++
> > >  3 files changed, 41 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> > > index e176d57..64814fc 100644
> > > --- a/libavcodec/qsvenc.c
> > > +++ b/libavcodec/qsvenc.c
> > > @@ -139,6 +139,9 @@ static void dump_video_param(AVCodecContext
> > *avctx, QSVEncContext *q,
> > >  #if QSV_HAVE_CO3
> > >      mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
> > >  #endif
> > > +#if QSV_HAVE_EXT_HEVC_TILES
> > > +    mfxExtHEVCTiles *exthevctiles = (mfxExtHEVCTiles *)coding_opts[3 +
> > QSV_HAVE_CO_VPS];
> >
> > Should change QSV_HAVE_CO_VPS to QSV_HAVE_EXT_HEVC_TILES?
>
> There is possibility(MSDK version between 1.13 and 1.17) that MSDK has
> MFX_EXTBUFF_HEVC_TILES buffer but has no MFX_EXT_BUFF_CODING_OPTION_VPS
> buffer.
>
> ext_buffers[]:
> BUF_CO | BUF_CO2 | BUF_CO3 | BUF_VPS | BUF_TILE |...
>
> Hence I'd like to check QSV_HAVE_CO_VPS to get the exact address of
> BUF_TILE
> to dump the truly set values.
>
> >
> > > +#endif
> > >
> > >      av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",
> > >             print_profile(info->CodecProfile), info->CodecLevel);
> > > @@ -204,6 +207,12 @@ static void dump_video_param(AVCodecContext
> > *avctx, QSVEncContext *q,
> > >      av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n",
> > >             print_threestate(co->RateDistortionOpt));
> > >
> > > +#if QSV_HAVE_EXT_HEVC_TILES
> > > +    if (avctx->codec_id == AV_CODEC_ID_HEVC)
> > > +        av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16";
> > NumTileRows: %"PRIu16"\n",
> > > +               exthevctiles->NumTileColumns,
> exthevctiles->NumTileRows);
> > > +#endif
> > > +
> > >  #if QSV_HAVE_CO2
> > >      av_log(avctx, AV_LOG_VERBOSE,
> > >             "RecoveryPointSEI: %s IntRefType: %"PRIu16";
> > IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n",
> > > @@ -771,6 +780,16 @@ FF_ENABLE_DEPRECATION_WARNINGS
> > >      }
> > >  #endif
> > >
> > > +#if QSV_HAVE_EXT_HEVC_TILES
> > > +    if (avctx->codec_id == AV_CODEC_ID_HEVC) {
> > > +        q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES;
> > > +        q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles);
> > > +        q->exthevctiles.NumTileColumns  = q->tile_cols;
> > > +        q->exthevctiles.NumTileRows     = q->tile_rows;
> > > +        q->extparam_internal[q->nb_extparam_internal++] =
> (mfxExtBuffer
> > *)&q->exthevctiles;
> > > +    }
> > > +#endif
> > > +
> > >      if (!check_enc_param(avctx,q)) {
> > >          av_log(avctx, AV_LOG_ERROR,
> > >                 "some encoding parameters are not supported by the QSV
> "
> > > @@ -887,7 +906,14 @@ static int
> > qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
> > >      };
> > >  #endif
> > >
> > > -    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 +
> > QSV_HAVE_CO_VPS];
> > > +#if QSV_HAVE_EXT_HEVC_TILES
> > > +    mfxExtHEVCTiles hevc_tile_buf = {
> > > +         .Header.BufferId = MFX_EXTBUFF_HEVC_TILES,
> > > +         .Header.BufferSz = sizeof(hevc_tile_buf),
> > > +    };
> > > +#endif
> > > +
> > > +    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 +
> > QSV_HAVE_CO_VPS + QSV_HAVE_EXT_HEVC_TILES];
> > >
> > >      int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
> > >      int ret, ext_buf_num = 0, extradata_offset = 0;
> > > @@ -905,6 +931,10 @@ static int
> > qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
> > >      if (q->hevc_vps)
> > >          ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata_vps;
> > >  #endif
> > > +#if QSV_HAVE_EXT_HEVC_TILES
> > > +    if (avctx->codec_id == AV_CODEC_ID_HEVC)
> > > +        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&hevc_tile_buf;
> > > +#endif
> > >
> > >      q->param.ExtParam    = ext_buffers;
> > >      q->param.NumExtParam = ext_buf_num;
> > > diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
> > > index ee35582..6609171 100644
> > > --- a/libavcodec/qsvenc.h
> > > +++ b/libavcodec/qsvenc.h
> > > @@ -38,6 +38,7 @@
> > >  #define QSV_HAVE_CO3 QSV_VERSION_ATLEAST(1, 11)
> > >  #define QSV_HAVE_CO_VPS  QSV_VERSION_ATLEAST(1, 17)
> > >
> > > +#define QSV_HAVE_EXT_HEVC_TILES QSV_VERSION_ATLEAST(1, 13)
> > >  #define QSV_HAVE_EXT_VP9_PARAM QSV_VERSION_ATLEAST(1, 26)
> > >
> > >  #define QSV_HAVE_TRELLIS QSV_VERSION_ATLEAST(1, 8)
> > > @@ -124,6 +125,9 @@ typedef struct QSVEncContext {
> > >      mfxExtMultiFrameParam   extmfp;
> > >      mfxExtMultiFrameControl extmfc;
> > >  #endif
> > > +#if QSV_HAVE_EXT_HEVC_TILES
> > > +    mfxExtHEVCTiles exthevctiles;
> > > +#endif
> > >  #if QSV_HAVE_EXT_VP9_PARAM
> > >      mfxExtVP9Param  extvp9param;
> > >  #endif
> > > @@ -161,6 +165,9 @@ typedef struct QSVEncContext {
> > >      int max_frame_size;
> > >      int max_slice_size;
> > >
> > > +    int tile_cols;
> > > +    int tile_rows;
> > > +
> > >      int aud;
> > >
> > >      int single_sei_nal_unit;
> > > diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c
> > > index da64b4c..27e2232 100644
> > > --- a/libavcodec/qsvenc_hevc.c
> > > +++ b/libavcodec/qsvenc_hevc.c
> > > @@ -243,6 +243,9 @@ static const AVOption options[] = {
> > >
> > >      { "gpb", "1: GPB (generalized P/B frame); 0: regular P frame",
> > OFFSET(qsv.gpb), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE},
> > >
> > > +    { "tile_cols",  "Number of columns for tiled encoding",
> > OFFSET(qsv.tile_cols),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX,
> VE },
> >
> > should better to keep consist with other codecs such as vp9/av1 to set
> > the name as tile_columns.
> >
> > And I note the value is log2 in these codecs.
>
> Yes, I've noticed the name and values in log2 formats.
> BTW, MSDK allows Tile structures (such as 3x3 Tiles) instead of only 2^..
> Tiles,
> would it be better to use log2 format to set the rows/columns?
>
> > > +    { "tile_rows",  "Number of rows for tiled encoding",
> > OFFSET(qsv.tile_rows),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX,
> VE },
> > > +
> > >      { NULL },
> > >  };
> > >
> > > --
>
>
Ping,
Zhong Li Dec. 8, 2019, 8:32 a.m. UTC | #7
Linjie Fu <linjie.fu@intel.com> 于2019年11月26日周二 下午12:04写道:
>
> Add -tile_rows and -tile_cols option to specify the number of tile rows
> and columns for ICL+ (gen 11) platform.
>
> A tile must wholly contain all the slices within it. Slices cannot cross
> tile boundaries. So the slice number would be implicitly resized to the
> max(nSlice, nTile).
>
> Example:
>     ffmpeg -v verbose -hwaccel qsv -init_hw_device qsv=hw
>     -filter_hw_device hw -f rawvideo -s:v 1920x1080 -i ./input.nv12 -vf
>     format=nv12,hwupload=extra_hw_frames=64 -c:v hevc_qsv -tile_rows 2
>     -tile_cols 2 -slices 4 -y output.h265
>
> Also dump the actual quantity of encoded tiled rows and columns in run
> time.
>
> Fix the enhancement #8400.
>
> Signed-off-by: Linjie Fu <linjie.fu@intel.com>
> ---
>  libavcodec/qsvenc.c      | 32 +++++++++++++++++++++++++++++++-
>  libavcodec/qsvenc.h      |  7 +++++++
>  libavcodec/qsvenc_hevc.c |  3 +++
>  3 files changed, 41 insertions(+), 1 deletion(-)
>
> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> index e176d57..64814fc 100644
> --- a/libavcodec/qsvenc.c
> +++ b/libavcodec/qsvenc.c
> @@ -139,6 +139,9 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
>  #if QSV_HAVE_CO3
>      mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
>  #endif
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    mfxExtHEVCTiles *exthevctiles = (mfxExtHEVCTiles *)coding_opts[3 + QSV_HAVE_CO_VPS];
> +#endif
>
>      av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",
>             print_profile(info->CodecProfile), info->CodecLevel);
> @@ -204,6 +207,12 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
>      av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n",
>             print_threestate(co->RateDistortionOpt));
>
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    if (avctx->codec_id == AV_CODEC_ID_HEVC)
> +        av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16"; NumTileRows: %"PRIu16"\n",
> +               exthevctiles->NumTileColumns, exthevctiles->NumTileRows);
> +#endif
> +
>  #if QSV_HAVE_CO2
>      av_log(avctx, AV_LOG_VERBOSE,
>             "RecoveryPointSEI: %s IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n",
> @@ -771,6 +780,16 @@ FF_ENABLE_DEPRECATION_WARNINGS
>      }
>  #endif
>
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    if (avctx->codec_id == AV_CODEC_ID_HEVC) {
> +        q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES;
> +        q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles);
> +        q->exthevctiles.NumTileColumns  = q->tile_cols;
> +        q->exthevctiles.NumTileRows     = q->tile_rows;
> +        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->exthevctiles;
> +    }
> +#endif
> +
>      if (!check_enc_param(avctx,q)) {
>          av_log(avctx, AV_LOG_ERROR,
>                 "some encoding parameters are not supported by the QSV "
> @@ -887,7 +906,14 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
>      };
>  #endif
>
> -    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS];
> +#if QSV_HAVE_EXT_HEVC_TILES
> +    mfxExtHEVCTiles hevc_tile_buf = {
> +         .Header.BufferId = MFX_EXTBUFF_HEVC_TILES,
> +         .Header.BufferSz = sizeof(hevc_tile_buf),
> +    };
> +#endif
> +
> +    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS + QSV_HAVE_EXT_HEVC_TILES];

Should be checked with #if QSV_HAVE_EXT_HEVC_TILES""

The reset LGTM.
Fu, Linjie Dec. 10, 2019, 12:56 a.m. UTC | #8
> -----Original Message-----

> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of

> Zhong Li

> Sent: Sunday, December 8, 2019 16:32

> To: FFmpeg development discussions and patches <ffmpeg-

> devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] [PATCH] lavc/qsvenc: add Tiles encode support

> for HEVC

> 

> Linjie Fu <linjie.fu@intel.com> 于2019年11月26日周二 下午12:04写道:

> >

> > Add -tile_rows and -tile_cols option to specify the number of tile rows

> > and columns for ICL+ (gen 11) platform.

> >

> > A tile must wholly contain all the slices within it. Slices cannot cross

> > tile boundaries. So the slice number would be implicitly resized to the

> > max(nSlice, nTile).

> >

> > Example:

> >     ffmpeg -v verbose -hwaccel qsv -init_hw_device qsv=hw

> >     -filter_hw_device hw -f rawvideo -s:v 1920x1080 -i ./input.nv12 -vf

> >     format=nv12,hwupload=extra_hw_frames=64 -c:v hevc_qsv -tile_rows 2

> >     -tile_cols 2 -slices 4 -y output.h265

> >

> > Also dump the actual quantity of encoded tiled rows and columns in run

> > time.

> >

> > Fix the enhancement #8400.

> >

> > Signed-off-by: Linjie Fu <linjie.fu@intel.com>

> > ---

> >  libavcodec/qsvenc.c      | 32 +++++++++++++++++++++++++++++++-

> >  libavcodec/qsvenc.h      |  7 +++++++

> >  libavcodec/qsvenc_hevc.c |  3 +++

> >  3 files changed, 41 insertions(+), 1 deletion(-)

> >

> > diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c

> > index e176d57..64814fc 100644

> > --- a/libavcodec/qsvenc.c

> > +++ b/libavcodec/qsvenc.c

> > @@ -139,6 +139,9 @@ static void dump_video_param(AVCodecContext

> *avctx, QSVEncContext *q,

> >  #if QSV_HAVE_CO3

> >      mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];

> >  #endif

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    mfxExtHEVCTiles *exthevctiles = (mfxExtHEVCTiles *)coding_opts[3 +

> QSV_HAVE_CO_VPS];

> > +#endif

> >

> >      av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",

> >             print_profile(info->CodecProfile), info->CodecLevel);

> > @@ -204,6 +207,12 @@ static void dump_video_param(AVCodecContext

> *avctx, QSVEncContext *q,

> >      av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n",

> >             print_threestate(co->RateDistortionOpt));

> >

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    if (avctx->codec_id == AV_CODEC_ID_HEVC)

> > +        av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16";

> NumTileRows: %"PRIu16"\n",

> > +               exthevctiles->NumTileColumns, exthevctiles->NumTileRows);

> > +#endif

> > +

> >  #if QSV_HAVE_CO2

> >      av_log(avctx, AV_LOG_VERBOSE,

> >             "RecoveryPointSEI: %s IntRefType: %"PRIu16";

> IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n",

> > @@ -771,6 +780,16 @@ FF_ENABLE_DEPRECATION_WARNINGS

> >      }

> >  #endif

> >

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    if (avctx->codec_id == AV_CODEC_ID_HEVC) {

> > +        q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES;

> > +        q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles);

> > +        q->exthevctiles.NumTileColumns  = q->tile_cols;

> > +        q->exthevctiles.NumTileRows     = q->tile_rows;

> > +        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer

> *)&q->exthevctiles;

> > +    }

> > +#endif

> > +

> >      if (!check_enc_param(avctx,q)) {

> >          av_log(avctx, AV_LOG_ERROR,

> >                 "some encoding parameters are not supported by the QSV "

> > @@ -887,7 +906,14 @@ static int

> qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)

> >      };

> >  #endif

> >

> > -    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 +

> QSV_HAVE_CO_VPS];

> > +#if QSV_HAVE_EXT_HEVC_TILES

> > +    mfxExtHEVCTiles hevc_tile_buf = {

> > +         .Header.BufferId = MFX_EXTBUFF_HEVC_TILES,

> > +         .Header.BufferSz = sizeof(hevc_tile_buf),

> > +    };

> > +#endif

> > +

> > +    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 +

> QSV_HAVE_CO_VPS + QSV_HAVE_EXT_HEVC_TILES];

> 

> Should be checked with #if QSV_HAVE_EXT_HEVC_TILES""


Hi,

IMHO the check may be redundant. If  the version of MSDK  < 1.13,
QSV_HAVE_EXT_HEVC_TILES equals 0,  above expression is identical to
mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS + 0];

And there is no version check for CO2/CO3/VPS.

> The reset LGTM.


Thanks for the review.

- linjie
Zhong Li Dec. 12, 2019, 1:01 p.m. UTC | #9
Will apply.
Thanks!

Fu, Linjie <linjie.fu@intel.com> 于2019年12月10日周二 上午8:57写道:
>
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > Zhong Li
> > Sent: Sunday, December 8, 2019 16:32
> > To: FFmpeg development discussions and patches <ffmpeg-
> > devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [PATCH] lavc/qsvenc: add Tiles encode support
> > for HEVC
> >
> > Linjie Fu <linjie.fu@intel.com> 于2019年11月26日周二 下午12:04写道:
> > >
> > > Add -tile_rows and -tile_cols option to specify the number of tile rows
> > > and columns for ICL+ (gen 11) platform.
> > >
> > > A tile must wholly contain all the slices within it. Slices cannot cross
> > > tile boundaries. So the slice number would be implicitly resized to the
> > > max(nSlice, nTile).
> > >
> > > Example:
> > >     ffmpeg -v verbose -hwaccel qsv -init_hw_device qsv=hw
> > >     -filter_hw_device hw -f rawvideo -s:v 1920x1080 -i ./input.nv12 -vf
> > >     format=nv12,hwupload=extra_hw_frames=64 -c:v hevc_qsv -tile_rows 2
> > >     -tile_cols 2 -slices 4 -y output.h265
> > >
> > > Also dump the actual quantity of encoded tiled rows and columns in run
> > > time.
> > >
> > > Fix the enhancement #8400.
> > >
> > > Signed-off-by: Linjie Fu <linjie.fu@intel.com>
> > > ---
> > >  libavcodec/qsvenc.c      | 32 +++++++++++++++++++++++++++++++-
> > >  libavcodec/qsvenc.h      |  7 +++++++
> > >  libavcodec/qsvenc_hevc.c |  3 +++
> > >  3 files changed, 41 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> > > index e176d57..64814fc 100644
> > > --- a/libavcodec/qsvenc.c
> > > +++ b/libavcodec/qsvenc.c
> > > @@ -139,6 +139,9 @@ static void dump_video_param(AVCodecContext
> > *avctx, QSVEncContext *q,
> > >  #if QSV_HAVE_CO3
> > >      mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
> > >  #endif
> > > +#if QSV_HAVE_EXT_HEVC_TILES
> > > +    mfxExtHEVCTiles *exthevctiles = (mfxExtHEVCTiles *)coding_opts[3 +
> > QSV_HAVE_CO_VPS];
> > > +#endif
> > >
> > >      av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",
> > >             print_profile(info->CodecProfile), info->CodecLevel);
> > > @@ -204,6 +207,12 @@ static void dump_video_param(AVCodecContext
> > *avctx, QSVEncContext *q,
> > >      av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n",
> > >             print_threestate(co->RateDistortionOpt));
> > >
> > > +#if QSV_HAVE_EXT_HEVC_TILES
> > > +    if (avctx->codec_id == AV_CODEC_ID_HEVC)
> > > +        av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16";
> > NumTileRows: %"PRIu16"\n",
> > > +               exthevctiles->NumTileColumns, exthevctiles->NumTileRows);
> > > +#endif
> > > +
> > >  #if QSV_HAVE_CO2
> > >      av_log(avctx, AV_LOG_VERBOSE,
> > >             "RecoveryPointSEI: %s IntRefType: %"PRIu16";
> > IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n",
> > > @@ -771,6 +780,16 @@ FF_ENABLE_DEPRECATION_WARNINGS
> > >      }
> > >  #endif
> > >
> > > +#if QSV_HAVE_EXT_HEVC_TILES
> > > +    if (avctx->codec_id == AV_CODEC_ID_HEVC) {
> > > +        q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES;
> > > +        q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles);
> > > +        q->exthevctiles.NumTileColumns  = q->tile_cols;
> > > +        q->exthevctiles.NumTileRows     = q->tile_rows;
> > > +        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer
> > *)&q->exthevctiles;
> > > +    }
> > > +#endif
> > > +
> > >      if (!check_enc_param(avctx,q)) {
> > >          av_log(avctx, AV_LOG_ERROR,
> > >                 "some encoding parameters are not supported by the QSV "
> > > @@ -887,7 +906,14 @@ static int
> > qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
> > >      };
> > >  #endif
> > >
> > > -    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 +
> > QSV_HAVE_CO_VPS];
> > > +#if QSV_HAVE_EXT_HEVC_TILES
> > > +    mfxExtHEVCTiles hevc_tile_buf = {
> > > +         .Header.BufferId = MFX_EXTBUFF_HEVC_TILES,
> > > +         .Header.BufferSz = sizeof(hevc_tile_buf),
> > > +    };
> > > +#endif
> > > +
> > > +    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 +
> > QSV_HAVE_CO_VPS + QSV_HAVE_EXT_HEVC_TILES];
> >
> > Should be checked with #if QSV_HAVE_EXT_HEVC_TILES""
>
> Hi,
>
> IMHO the check may be redundant. If  the version of MSDK  < 1.13,
> QSV_HAVE_EXT_HEVC_TILES equals 0,  above expression is identical to
> mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS + 0];
>
> And there is no version check for CO2/CO3/VPS.
>
> > The reset LGTM.
>
> Thanks for the review.
>
> - linjie
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
diff mbox

Patch

diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index e176d57..64814fc 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -139,6 +139,9 @@  static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
 #if QSV_HAVE_CO3
     mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
 #endif
+#if QSV_HAVE_EXT_HEVC_TILES
+    mfxExtHEVCTiles *exthevctiles = (mfxExtHEVCTiles *)coding_opts[3 + QSV_HAVE_CO_VPS];
+#endif
 
     av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",
            print_profile(info->CodecProfile), info->CodecLevel);
@@ -204,6 +207,12 @@  static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
     av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n",
            print_threestate(co->RateDistortionOpt));
 
+#if QSV_HAVE_EXT_HEVC_TILES
+    if (avctx->codec_id == AV_CODEC_ID_HEVC)
+        av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16"; NumTileRows: %"PRIu16"\n",
+               exthevctiles->NumTileColumns, exthevctiles->NumTileRows);
+#endif
+
 #if QSV_HAVE_CO2
     av_log(avctx, AV_LOG_VERBOSE,
            "RecoveryPointSEI: %s IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n",
@@ -771,6 +780,16 @@  FF_ENABLE_DEPRECATION_WARNINGS
     }
 #endif
 
+#if QSV_HAVE_EXT_HEVC_TILES
+    if (avctx->codec_id == AV_CODEC_ID_HEVC) {
+        q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES;
+        q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles);
+        q->exthevctiles.NumTileColumns  = q->tile_cols;
+        q->exthevctiles.NumTileRows     = q->tile_rows;
+        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->exthevctiles;
+    }
+#endif
+
     if (!check_enc_param(avctx,q)) {
         av_log(avctx, AV_LOG_ERROR,
                "some encoding parameters are not supported by the QSV "
@@ -887,7 +906,14 @@  static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
     };
 #endif
 
-    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS];
+#if QSV_HAVE_EXT_HEVC_TILES
+    mfxExtHEVCTiles hevc_tile_buf = {
+         .Header.BufferId = MFX_EXTBUFF_HEVC_TILES,
+         .Header.BufferSz = sizeof(hevc_tile_buf),
+    };
+#endif
+
+    mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS + QSV_HAVE_EXT_HEVC_TILES];
 
     int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
     int ret, ext_buf_num = 0, extradata_offset = 0;
@@ -905,6 +931,10 @@  static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
     if (q->hevc_vps)
         ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata_vps;
 #endif
+#if QSV_HAVE_EXT_HEVC_TILES
+    if (avctx->codec_id == AV_CODEC_ID_HEVC)
+        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&hevc_tile_buf;
+#endif
 
     q->param.ExtParam    = ext_buffers;
     q->param.NumExtParam = ext_buf_num;
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index ee35582..6609171 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -38,6 +38,7 @@ 
 #define QSV_HAVE_CO3 QSV_VERSION_ATLEAST(1, 11)
 #define QSV_HAVE_CO_VPS  QSV_VERSION_ATLEAST(1, 17)
 
+#define QSV_HAVE_EXT_HEVC_TILES QSV_VERSION_ATLEAST(1, 13)
 #define QSV_HAVE_EXT_VP9_PARAM QSV_VERSION_ATLEAST(1, 26)
 
 #define QSV_HAVE_TRELLIS QSV_VERSION_ATLEAST(1, 8)
@@ -124,6 +125,9 @@  typedef struct QSVEncContext {
     mfxExtMultiFrameParam   extmfp;
     mfxExtMultiFrameControl extmfc;
 #endif
+#if QSV_HAVE_EXT_HEVC_TILES
+    mfxExtHEVCTiles exthevctiles;
+#endif
 #if QSV_HAVE_EXT_VP9_PARAM
     mfxExtVP9Param  extvp9param;
 #endif
@@ -161,6 +165,9 @@  typedef struct QSVEncContext {
     int max_frame_size;
     int max_slice_size;
 
+    int tile_cols;
+    int tile_rows;
+
     int aud;
 
     int single_sei_nal_unit;
diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c
index da64b4c..27e2232 100644
--- a/libavcodec/qsvenc_hevc.c
+++ b/libavcodec/qsvenc_hevc.c
@@ -243,6 +243,9 @@  static const AVOption options[] = {
 
     { "gpb", "1: GPB (generalized P/B frame); 0: regular P frame", OFFSET(qsv.gpb), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE},
 
+    { "tile_cols",  "Number of columns for tiled encoding",   OFFSET(qsv.tile_cols),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE },
+    { "tile_rows",  "Number of rows for tiled encoding",      OFFSET(qsv.tile_rows),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE },
+
     { NULL },
 };