@ -104,9 +104,30 @@ typedef struct VAAPIEncodeH264Context {
int64_t idr_pic_count ;
int64_t last_idr_frame ;
// RefPicList management.
// Rate control configuration.
struct {
VAEncMiscParameterBuffer misc ;
VAEncMiscParameterRateControl rc ;
} rc_params ;
struct {
VAEncMiscParameterBuffer misc ;
VAEncMiscParameterHRD hrd ;
} hrd_params ;
# if VA_CHECK_VERSION(0, 36, 0)
// Speed-quality tradeoff setting.
struct {
VAEncMiscParameterBuffer misc ;
VAEncMiscParameterBufferQualityLevel quality ;
} quality_params ;
# endif
} VAAPIEncodeH264Context ;
typedef struct VAAPIEncodeH264Options {
int qp ;
int quality ;
} VAAPIEncodeH264Options ;
# define vseq_var(name) vseq->name, name
# define vseq_field(name) vseq->seq_fields.bits.name, name
@ -506,6 +527,19 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
} else {
vseq - > frame_cropping_flag = 0 ;
}
vseq - > bits_per_second = avctx - > bit_rate ;
if ( avctx - > framerate . num > 0 & & avctx - > framerate . den > 0 ) {
vseq - > num_units_in_tick = avctx - > framerate . num ;
vseq - > time_scale = 2 * avctx - > framerate . den ;
} else {
vseq - > num_units_in_tick = avctx - > time_base . num ;
vseq - > time_scale = 2 * avctx - > time_base . den ;
}
vseq - > intra_period = ctx - > p_per_i * ( ctx - > b_per_p + 1 ) ;
vseq - > intra_idr_period = vseq - > intra_period ;
vseq - > ip_period = ctx - > b_per_p + 1 ;
}
{
@ -690,20 +724,94 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx,
return 0 ;
}
static VAConfigAttrib vaapi_encode_h264_config_attributes [ ] = {
{ . type = VAConfigAttribRTFormat ,
. value = VA_RT_FORMAT_YUV420 } ,
{ . type = VAConfigAttribRateControl ,
. value = VA_RC_CQP } ,
{ . type = VAConfigAttribEncPackedHeaders ,
. value = ( VA_ENC_PACKED_HEADER_SEQUENCE |
VA_ENC_PACKED_HEADER_SLICE ) } ,
} ;
static av_cold int vaapi_encode_h264_init_constant_bitrate ( AVCodecContext * avctx )
{
VAAPIEncodeContext * ctx = avctx - > priv_data ;
VAAPIEncodeH264Context * priv = ctx - > priv_data ;
int hrd_buffer_size ;
int hrd_initial_buffer_fullness ;
if ( avctx - > rc_buffer_size )
hrd_buffer_size = avctx - > rc_buffer_size ;
else
hrd_buffer_size = avctx - > bit_rate ;
if ( avctx - > rc_initial_buffer_occupancy )
hrd_initial_buffer_fullness = avctx - > rc_initial_buffer_occupancy ;
else
hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4 ;
priv - > rc_params . misc . type = VAEncMiscParameterTypeRateControl ;
priv - > rc_params . rc = ( VAEncMiscParameterRateControl ) {
. bits_per_second = avctx - > bit_rate ,
. target_percentage = 66 ,
. window_size = 1000 ,
. initial_qp = ( avctx - > qmax > = 0 ? avctx - > qmax : 40 ) ,
. min_qp = ( avctx - > qmin > = 0 ? avctx - > qmin : 18 ) ,
. basic_unit_size = 0 ,
} ;
ctx - > global_params [ ctx - > nb_global_params ] =
& priv - > rc_params . misc ;
ctx - > global_params_size [ ctx - > nb_global_params + + ] =
sizeof ( priv - > rc_params ) ;
priv - > hrd_params . misc . type = VAEncMiscParameterTypeHRD ;
priv - > hrd_params . hrd = ( VAEncMiscParameterHRD ) {
. initial_buffer_fullness = hrd_initial_buffer_fullness ,
. buffer_size = hrd_buffer_size ,
} ;
ctx - > global_params [ ctx - > nb_global_params ] =
& priv - > hrd_params . misc ;
ctx - > global_params_size [ ctx - > nb_global_params + + ] =
sizeof ( priv - > hrd_params ) ;
// These still need to be set for pic_init_qp/slice_qp_delta.
priv - > fixed_qp_idr = 26 ;
priv - > fixed_qp_p = 26 ;
priv - > fixed_qp_b = 26 ;
av_log ( avctx , AV_LOG_DEBUG , " Using constant-bitrate = %d bps. \n " ,
avctx - > bit_rate ) ;
return 0 ;
}
static av_cold int vaapi_encode_h264_init_fixed_qp ( AVCodecContext * avctx )
{
VAAPIEncodeContext * ctx = avctx - > priv_data ;
VAAPIEncodeH264Context * priv = ctx - > priv_data ;
VAAPIEncodeH264Options * opt = ctx - > codec_options ;
priv - > fixed_qp_p = opt - > qp ;
if ( avctx - > i_quant_factor > 0.0 )
priv - > fixed_qp_idr = ( int ) ( ( priv - > fixed_qp_p * avctx - > i_quant_factor +
avctx - > i_quant_offset ) + 0.5 ) ;
else
priv - > fixed_qp_idr = priv - > fixed_qp_p ;
if ( avctx - > b_quant_factor > 0.0 )
priv - > fixed_qp_b = ( int ) ( ( priv - > fixed_qp_p * avctx - > b_quant_factor +
avctx - > b_quant_offset ) + 0.5 ) ;
else
priv - > fixed_qp_b = priv - > fixed_qp_p ;
av_log ( avctx , AV_LOG_DEBUG , " Using fixed QP = "
" %d / %d / %d for IDR / P / B frames. \n " ,
priv - > fixed_qp_idr , priv - > fixed_qp_p , priv - > fixed_qp_b ) ;
return 0 ;
}
static av_cold int vaapi_encode_h264_init_internal ( AVCodecContext * avctx )
{
static const VAConfigAttrib default_config_attributes [ ] = {
{ . type = VAConfigAttribRTFormat ,
. value = VA_RT_FORMAT_YUV420 } ,
{ . type = VAConfigAttribEncPackedHeaders ,
. value = ( VA_ENC_PACKED_HEADER_SEQUENCE |
VA_ENC_PACKED_HEADER_SLICE ) } ,
} ;
VAAPIEncodeContext * ctx = avctx - > priv_data ;
VAAPIEncodeH264Context * priv = ctx - > priv_data ;
VAAPIEncodeH264Options * opt = ctx - > codec_options ;
int i , err ;
switch ( avctx - > profile ) {
case FF_PROFILE_H264_CONSTRAINED_BASELINE :
@ -744,8 +852,6 @@ static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx)
}
ctx - > va_entrypoint = VAEntrypointEncSlice ;
ctx - > va_rc_mode = VA_RC_CQP ;
ctx - > input_width = avctx - > width ;
ctx - > input_height = avctx - > height ;
ctx - > aligned_width = FFALIGN ( ctx - > input_width , 16 ) ;
@ -753,29 +859,41 @@ static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx)
priv - > mb_width = ctx - > aligned_width / 16 ;
priv - > mb_height = ctx - > aligned_height / 16 ;
for ( i = 0 ; i < FF_ARRAY_ELEMS ( default_config_attributes ) ; i + + ) {
ctx - > config_attributes [ ctx - > nb_config_attributes + + ] =
default_config_attributes [ i ] ;
}
if ( avctx - > bit_rate > 0 ) {
av_log ( avctx , AV_LOG_ERROR , " Constant bitrate encoding is not "
" supported! \n " ) ;
return AVERROR_PATCHWELCOME ;
ctx - > va_rc_mode = VA_RC_CBR ;
err = vaapi_encode_h264_init_constant_bitrate ( avctx ) ;
} else {
ctx - > va_rc_mode = VA_RC_CQP ;
err = vaapi_encode_h264_init_fixed_qp ( avctx ) ;
}
if ( err < 0 )
return err ;
priv - > fixed_qp_p = avctx - > global_quality ;
if ( avctx - > i_quant_factor > 0.0 )
priv - > fixed_qp_idr = ( int ) ( ( priv - > fixed_qp_p * avctx - > i_quant_factor +
avctx - > i_quant_offset ) + 0.5 ) ;
else
priv - > fixed_qp_idr = priv - > fixed_qp_p ;
if ( avctx - > b_quant_factor > 0.0 )
priv - > fixed_qp_b = ( int ) ( ( priv - > fixed_qp_p * avctx - > b_quant_factor +
avctx - > b_quant_offset ) + 0.5 ) ;
else
priv - > fixed_qp_b = priv - > fixed_qp_p ;
av_log ( avctx , AV_LOG_DEBUG , " QP = %d / %d / %d for IDR / P / B frames. \n " ,
priv - > fixed_qp_idr , priv - > fixed_qp_p , priv - > fixed_qp_b ) ;
ctx - > config_attributes [ ctx - > nb_config_attributes + + ] = ( VAConfigAttrib ) {
. type = VAConfigAttribRateControl ,
. value = ctx - > va_rc_mode ,
} ;
ctx - > config_attributes = vaapi_encode_h264_config_attributes ;
ctx - > nb_config_attributes =
FF_ARRAY_ELEMS ( vaapi_encode_h264_config_attributes ) ;
if ( opt - > quality > 0 ) {
# if VA_CHECK_VERSION(0, 36, 0)
priv - > quality_params . misc . type =
VAEncMiscParameterTypeQualityLevel ;
priv - > quality_params . quality . quality_level = opt - > quality ;
ctx - > global_params [ ctx - > nb_global_params ] =
& priv - > quality_params . misc ;
ctx - > global_params_size [ ctx - > nb_global_params + + ] =
sizeof ( priv - > quality_params ) ;
# else
av_log ( avctx , AV_LOG_WARNING , " The encode quality option is not "
" supported with this VAAPI version. \n " ) ;
# endif
}
ctx - > nb_recon_frames = 20 ;
@ -808,13 +926,23 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx)
return ff_vaapi_encode_init ( avctx , & vaapi_encode_type_h264 ) ;
}
# define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \
offsetof ( VAAPIEncodeH264Options , x ) )
# define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
static const AVOption vaapi_encode_h264_options [ ] = {
{ " qp " , " Constant QP (for P frames; scaled by qfactor/qoffset for I/B) " ,
OFFSET ( qp ) , AV_OPT_TYPE_INT , { . i64 = 20 } , 0 , 52 , FLAGS } ,
{ " quality " , " Set encode quality (trades off against speed, higher is faster) " ,
OFFSET ( quality ) , AV_OPT_TYPE_INT , { . i64 = 0 } , 0 , 2 , FLAGS } ,
{ NULL } ,
} ;
static const AVCodecDefault vaapi_encode_h264_defaults [ ] = {
{ " profile " , " 100 " } ,
{ " level " , " 51 " } ,
{ " b " , " 0 " } ,
{ " bf " , " 2 " } ,
{ " g " , " 120 " } ,
{ " global_quality " , " 20 " } ,
{ " i_qfactor " , " 1.0 " } ,
{ " i_qoffset " , " 0.0 " } ,
{ " b_qfactor " , " 1.2 " } ,
@ -825,6 +953,7 @@ static const AVCodecDefault vaapi_encode_h264_defaults[] = {
static const AVClass vaapi_encode_h264_class = {
. class_name = " h264_vaapi " ,
. item_name = av_default_item_name ,
. option = vaapi_encode_h264_options ,
. version = LIBAVUTIL_VERSION_INT ,
} ;
@ -833,7 +962,8 @@ AVCodec ff_h264_vaapi_encoder = {
. long_name = NULL_IF_CONFIG_SMALL ( " H.264/AVC (VAAPI) " ) ,
. type = AVMEDIA_TYPE_VIDEO ,
. id = AV_CODEC_ID_H264 ,
. priv_data_size = sizeof ( VAAPIEncodeContext ) ,
. priv_data_size = ( sizeof ( VAAPIEncodeContext ) +
sizeof ( VAAPIEncodeH264Options ) ) ,
. init = & vaapi_encode_h264_init ,
. encode2 = & ff_vaapi_encode2 ,
. close = & ff_vaapi_encode_close ,