@ -146,6 +146,14 @@ static const struct {
{ MFX_RATECONTROL_QVBR , " QVBR " } ,
} ;
# define UPDATE_PARAM(a, b) \
do { \
if ( ( a ) ! = ( b ) ) { \
a = b ; \
updated = 1 ; \
} \
} while ( 0 ) \
static const char * print_ratecontrol ( mfxU16 rc_mode )
{
int i ;
@ -1613,6 +1621,83 @@ static int set_roi_encode_ctrl(AVCodecContext *avctx, const AVFrame *frame,
return 0 ;
}
static int update_qp ( AVCodecContext * avctx , QSVEncContext * q ,
const AVFrame * frame )
{
int updated = 0 , qp = 0 , new_qp ;
char * tail ;
AVDictionaryEntry * entry = NULL ;
if ( avctx - > codec_id ! = AV_CODEC_ID_H264 & & avctx - > codec_id ! = AV_CODEC_ID_HEVC )
return 0 ;
entry = av_dict_get ( frame - > metadata , " qsv_config_qp " , NULL , 0 ) ;
if ( entry & & q - > param . mfx . RateControlMethod = = MFX_RATECONTROL_CQP ) {
qp = strtol ( entry - > value , & tail , 10 ) ;
if ( * tail ) {
av_log ( avctx , AV_LOG_WARNING , " Invalid qsv_config_qp string. Ignore this metadata \n " ) ;
return 0 ;
}
if ( qp < 0 | | qp > 51 ) {
av_log ( avctx , AV_LOG_WARNING , " Invalid qp, clip to 0 ~ 51 \n " ) ;
qp = av_clip ( qp , 0 , 51 ) ;
}
av_log ( avctx , AV_LOG_DEBUG , " Configure qp: %d \n " , qp ) ;
UPDATE_PARAM ( q - > param . mfx . QPP , qp ) ;
new_qp = av_clip ( qp * fabs ( avctx - > i_quant_factor ) +
avctx - > i_quant_offset , 0 , 51 ) ;
UPDATE_PARAM ( q - > param . mfx . QPI , new_qp ) ;
new_qp = av_clip ( qp * fabs ( avctx - > b_quant_factor ) +
avctx - > b_quant_offset , 0 , 51 ) ;
UPDATE_PARAM ( q - > param . mfx . QPB , new_qp ) ;
av_log ( avctx , AV_LOG_DEBUG ,
" using fixed qp = %d/%d/%d for idr/p/b frames \n " ,
q - > param . mfx . QPI , q - > param . mfx . QPP , q - > param . mfx . QPB ) ;
}
return updated ;
}
static int update_parameters ( AVCodecContext * avctx , QSVEncContext * q ,
const AVFrame * frame )
{
int needReset = 0 , ret = 0 ;
if ( ! frame )
return 0 ;
needReset = update_qp ( avctx , q , frame ) ;
if ( ! needReset )
return 0 ;
if ( avctx - > hwaccel_context ) {
AVQSVContext * qsv = avctx - > hwaccel_context ;
int i , j ;
q - > param . ExtParam = q - > extparam ;
for ( i = 0 ; i < qsv - > nb_ext_buffers ; i + + )
q - > param . ExtParam [ i ] = qsv - > ext_buffers [ i ] ;
q - > param . NumExtParam = qsv - > nb_ext_buffers ;
for ( i = 0 ; i < q - > nb_extparam_internal ; i + + ) {
for ( j = 0 ; j < qsv - > nb_ext_buffers ; j + + ) {
if ( qsv - > ext_buffers [ j ] - > BufferId = = q - > extparam_internal [ i ] - > BufferId )
break ;
}
if ( j < qsv - > nb_ext_buffers )
continue ;
q - > param . ExtParam [ q - > param . NumExtParam + + ] = q - > extparam_internal [ i ] ;
}
} else {
q - > param . ExtParam = q - > extparam_internal ;
q - > param . NumExtParam = q - > nb_extparam_internal ;
}
av_log ( avctx , AV_LOG_DEBUG , " Parameter change, call msdk reset. \n " ) ;
ret = MFXVideoENCODE_Reset ( q - > session , & q - > param ) ;
if ( ret < 0 )
return ff_qsv_print_error ( avctx , ret , " Error during resetting " ) ;
return 0 ;
}
static int encode_frame ( AVCodecContext * avctx , QSVEncContext * q ,
const AVFrame * frame )
{
@ -1731,6 +1816,10 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
{
int ret ;
ret = update_parameters ( avctx , q , frame ) ;
if ( ret < 0 )
return ret ;
ret = encode_frame ( avctx , q , frame ) ;
if ( ret < 0 )
return ret ;