1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-11-21 10:55:51 +02:00

libavcodec/qsvenc: Add intra refresh to hevc_qsv and add new intra refresh parameter

Add intra refresh support to hevc_qsv as well.
Add an new intra refresh type: "horizontal", and an new param
ref_cycle_dist. This param specify the distance between the
beginnings of the intra-refresh cycles in frames.

Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
Signed-off-by: Haihao Xiang <haihao.xiang@intel.com>
This commit is contained in:
Wenbin Chen 2022-01-25 15:12:37 +08:00 committed by Haihao Xiang
parent 2ecc4fde5f
commit e102fd98d6
5 changed files with 54 additions and 10 deletions

View File

@ -3344,7 +3344,8 @@ Specifies intra refresh type. The major goal of intra refresh is improvement of
error resilience without significant impact on encoded bitstream size caused by error resilience without significant impact on encoded bitstream size caused by
I frames. The SDK encoder achieves this by encoding part of each frame in I frames. The SDK encoder achieves this by encoding part of each frame in
refresh cycle using intra MBs. @var{none} means no refresh. @var{vertical} means refresh cycle using intra MBs. @var{none} means no refresh. @var{vertical} means
vertical refresh, by column of MBs. vertical refresh, by column of MBs. To enable intra refresh, B frame should be
set to 0.
@item @var{int_ref_cycle_size} @item @var{int_ref_cycle_size}
Specifies number of pictures within refresh cycle starting from 2. 0 and 1 are Specifies number of pictures within refresh cycle starting from 2. 0 and 1 are
@ -3355,6 +3356,9 @@ Specifies QP difference for inserted intra MBs. This is signed value in
[-51, 51] range if target encoding bit-depth for luma samples is 8 and this [-51, 51] range if target encoding bit-depth for luma samples is 8 and this
range is [-63, 63] for 10 bit-depth or [-75, 75] for 12 bit-depth respectively. range is [-63, 63] for 10 bit-depth or [-75, 75] for 12 bit-depth respectively.
@item @var{int_ref_cycle_dist}
Distance between the beginnings of the intra-refresh cycles in frames.
@item @var{profile} @item @var{profile}
@table @samp @table @samp
@item unknown @item unknown
@ -3463,6 +3467,26 @@ Insert picture timing SEI with pic_struct_syntax element.
@item @var{transform_skip} @item @var{transform_skip}
Turn this option ON to enable transformskip. It is supported on platform equal Turn this option ON to enable transformskip. It is supported on platform equal
or newer than ICL. or newer than ICL.
@item @var{int_ref_type}
Specifies intra refresh type. The major goal of intra refresh is improvement of
error resilience without significant impact on encoded bitstream size caused by
I frames. The SDK encoder achieves this by encoding part of each frame in
refresh cycle using intra MBs. @var{none} means no refresh. @var{vertical} means
vertical refresh, by column of MBs. To enable intra refresh, B frame should be
set to 0.
@item @var{int_ref_cycle_size}
Specifies number of pictures within refresh cycle starting from 2. 0 and 1 are
invalid values.
@item @var{int_ref_qp_delta}
Specifies QP difference for inserted intra MBs. This is signed value in
[-51, 51] range if target encoding bit-depth for luma samples is 8 and this
range is [-63, 63] for 10 bit-depth or [-75, 75] for 12 bit-depth respectively.
@item @var{int_ref_cycle_dist}
Distance between the beginnings of the intra-refresh cycles in frames.
@end table @end table
@subsection MPEG2 Options @subsection MPEG2 Options

View File

@ -364,6 +364,10 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
#if QSV_VERSION_ATLEAST(1, 26) #if QSV_VERSION_ATLEAST(1, 26)
av_log(avctx, AV_LOG_VERBOSE, "TransformSkip: %s \n", print_threestate(co3->TransformSkip)); av_log(avctx, AV_LOG_VERBOSE, "TransformSkip: %s \n", print_threestate(co3->TransformSkip));
#endif #endif
#if QSV_VERSION_ATLEAST(1, 16)
av_log(avctx, AV_LOG_VERBOSE, "IntRefCycleDist: %"PRId16"\n", co3->IntRefCycleDist);
#endif
} }
static void dump_video_vp9_param(AVCodecContext *avctx, QSVEncContext *q, static void dump_video_vp9_param(AVCodecContext *avctx, QSVEncContext *q,
@ -865,13 +869,6 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
#if QSV_HAVE_CO2 #if QSV_HAVE_CO2
if (avctx->codec_id == AV_CODEC_ID_H264) { if (avctx->codec_id == AV_CODEC_ID_H264) {
if (q->int_ref_type >= 0)
q->extco2.IntRefType = q->int_ref_type;
if (q->int_ref_cycle_size >= 0)
q->extco2.IntRefCycleSize = q->int_ref_cycle_size;
if (q->int_ref_qp_delta != INT16_MIN)
q->extco2.IntRefQPDelta = q->int_ref_qp_delta;
if (q->bitrate_limit >= 0) if (q->bitrate_limit >= 0)
q->extco2.BitrateLimit = q->bitrate_limit ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; q->extco2.BitrateLimit = q->bitrate_limit ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
if (q->mbbrc >= 0) if (q->mbbrc >= 0)
@ -900,6 +897,12 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
q->extco2.ExtBRC = q->extbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; q->extco2.ExtBRC = q->extbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
if (q->max_frame_size >= 0) if (q->max_frame_size >= 0)
q->extco2.MaxFrameSize = q->max_frame_size; q->extco2.MaxFrameSize = q->max_frame_size;
if (q->int_ref_type >= 0)
q->extco2.IntRefType = q->int_ref_type;
if (q->int_ref_cycle_size >= 0)
q->extco2.IntRefCycleSize = q->int_ref_cycle_size;
if (q->int_ref_qp_delta != INT16_MIN)
q->extco2.IntRefQPDelta = q->int_ref_qp_delta;
#if QSV_HAVE_MAX_SLICE_SIZE #if QSV_HAVE_MAX_SLICE_SIZE
if (q->max_slice_size >= 0) if (q->max_slice_size >= 0)
q->extco2.MaxSliceSize = q->max_slice_size; q->extco2.MaxSliceSize = q->max_slice_size;
@ -973,6 +976,10 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
av_log(avctx, AV_LOG_WARNING, av_log(avctx, AV_LOG_WARNING,
"Please set max_b_frames(-bf) to 0 to enable P-pyramid\n"); "Please set max_b_frames(-bf) to 0 to enable P-pyramid\n");
} }
#endif
#if QSV_VERSION_ATLEAST(1, 16)
if (q->int_ref_cycle_dist >= 0)
q->extco3.IntRefCycleDist = q->int_ref_cycle_dist;
#endif #endif
} }

View File

@ -195,6 +195,7 @@ typedef struct QSVEncContext {
int int_ref_type; int int_ref_type;
int int_ref_cycle_size; int int_ref_cycle_size;
int int_ref_qp_delta; int int_ref_qp_delta;
int int_ref_cycle_dist;
int recovery_point_sei; int recovery_point_sei;
int repeat_pps; int repeat_pps;

View File

@ -126,13 +126,16 @@ static const AVOption options[] = {
{ "4x" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_4x }, INT_MIN, INT_MAX, VE, "look_ahead_downsampling" }, { "4x" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_4x }, INT_MIN, INT_MAX, VE, "look_ahead_downsampling" },
#endif #endif
{ "int_ref_type", "Intra refresh type", OFFSET(qsv.int_ref_type), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE, "int_ref_type" }, { "int_ref_type", "Intra refresh type. B frames should be set to 0.", OFFSET(qsv.int_ref_type), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE, "int_ref_type" },
{ "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .flags = VE, "int_ref_type" }, { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .flags = VE, "int_ref_type" },
{ "vertical", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .flags = VE, "int_ref_type" }, { "vertical", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .flags = VE, "int_ref_type" },
{ "horizontal", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, .flags = VE, "int_ref_type" },
{ "int_ref_cycle_size", "Number of frames in the intra refresh cycle", OFFSET(qsv.int_ref_cycle_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, { "int_ref_cycle_size", "Number of frames in the intra refresh cycle", OFFSET(qsv.int_ref_cycle_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE },
{ "int_ref_qp_delta", "QP difference for the refresh MBs", OFFSET(qsv.int_ref_qp_delta), AV_OPT_TYPE_INT, { .i64 = INT16_MIN }, INT16_MIN, INT16_MAX, VE }, { "int_ref_qp_delta", "QP difference for the refresh MBs", OFFSET(qsv.int_ref_qp_delta), AV_OPT_TYPE_INT, { .i64 = INT16_MIN }, INT16_MIN, INT16_MAX, VE },
{ "recovery_point_sei", "Insert recovery point SEI messages", OFFSET(qsv.recovery_point_sei), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, { "recovery_point_sei", "Insert recovery point SEI messages", OFFSET(qsv.recovery_point_sei), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE },
#if QSV_VERSION_ATLEAST(1, 16)
{ "int_ref_cycle_dist", "Distance between the beginnings of the intra-refresh cycles in frames", OFFSET(qsv.int_ref_cycle_dist), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT16_MAX, VE },
#endif
{ "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" }, { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" },
{ "unknown" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, { "unknown" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" },
{ "baseline", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, { "baseline", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_BASELINE }, INT_MIN, INT_MAX, VE, "profile" },

View File

@ -258,6 +258,15 @@ static const AVOption options[] = {
#if QSV_VERSION_ATLEAST(1, 26) #if QSV_VERSION_ATLEAST(1, 26)
{ "transform_skip", "Turn this option ON to enable transformskip", OFFSET(qsv.transform_skip), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 1, VE}, { "transform_skip", "Turn this option ON to enable transformskip", OFFSET(qsv.transform_skip), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 1, VE},
#endif #endif
{ "int_ref_type", "Intra refresh type. B frames should be set to 0", OFFSET(qsv.int_ref_type), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE, "int_ref_type" },
{ "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .flags = VE, "int_ref_type" },
{ "vertical", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .flags = VE, "int_ref_type" },
{ "horizontal", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, .flags = VE, "int_ref_type" },
{ "int_ref_cycle_size", "Number of frames in the intra refresh cycle", OFFSET(qsv.int_ref_cycle_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE },
{ "int_ref_qp_delta", "QP difference for the refresh MBs", OFFSET(qsv.int_ref_qp_delta), AV_OPT_TYPE_INT, { .i64 = INT16_MIN }, INT16_MIN, INT16_MAX, VE },
#if QSV_VERSION_ATLEAST(1, 16)
{ "int_ref_cycle_dist", "Distance between the beginnings of the intra-refresh cycles in frames", OFFSET(qsv.int_ref_cycle_dist), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT16_MAX, VE },
#endif
{ NULL }, { NULL },
}; };