/*
* This file is part of FFmpeg .
*
* FFmpeg is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* FFmpeg is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
# include "libavutil/internal.h"
# include "libavutil/opt.h"
# include "amfenc.h"
# include "codec_internal.h"
# include "internal.h"
# include <AMF/components/PreAnalysis.h>
# define OFFSET(x) offsetof(AmfContext, x)
# define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options [ ] = {
{ " usage " , " Set the encoding usage " , OFFSET ( usage ) , AV_OPT_TYPE_INT , { . i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING } , AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING , AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY_HIGH_QUALITY , VE , " usage " } ,
{ " transcoding " , " Generic Transcoding " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING } , 0 , 0 , VE , " usage " } ,
{ " ultralowlatency " , " ultra low latency trancoding " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY } , 0 , 0 , VE , " usage " } ,
{ " lowlatency " , " low latency trancoding " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY } , 0 , 0 , VE , " usage " } ,
{ " webcam " , " Webcam " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM } , 0 , 0 , VE , " usage " } ,
{ " high_quality " , " high quality trancoding " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_HIGH_QUALITY } , 0 , 0 , VE , " usage " } ,
{ " lowlatency_high_quality " , " low latency yet high quality trancoding " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY_HIGH_QUALITY } , 0 , 0 , VE , " usage " } ,
{ " profile " , " Set the profile (default main) " , OFFSET ( profile ) , AV_OPT_TYPE_INT , { . i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN } , AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN , AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN , VE , " profile " } ,
{ " main " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN } , 0 , 0 , VE , " profile " } ,
{ " profile_tier " , " Set the profile tier (default main) " , OFFSET ( tier ) , AV_OPT_TYPE_INT , { . i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN } , AMF_VIDEO_ENCODER_HEVC_TIER_MAIN , AMF_VIDEO_ENCODER_HEVC_TIER_HIGH , VE , " tier " } ,
{ " main " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN } , 0 , 0 , VE , " tier " } ,
{ " high " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_TIER_HIGH } , 0 , 0 , VE , " tier " } ,
{ " level " , " Set the encoding level (default auto) " , OFFSET ( level ) , AV_OPT_TYPE_INT , { . i64 = 0 } , 0 , AMF_LEVEL_6_2 , VE , " level " } ,
{ " auto " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = 0 } , 0 , 0 , VE , " level " } ,
{ " 1.0 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_1 } , 0 , 0 , VE , " level " } ,
{ " 2.0 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_2 } , 0 , 0 , VE , " level " } ,
{ " 2.1 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_2_1 } , 0 , 0 , VE , " level " } ,
{ " 3.0 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_3 } , 0 , 0 , VE , " level " } ,
{ " 3.1 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_3_1 } , 0 , 0 , VE , " level " } ,
{ " 4.0 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_4 } , 0 , 0 , VE , " level " } ,
{ " 4.1 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_4_1 } , 0 , 0 , VE , " level " } ,
{ " 5.0 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_5 } , 0 , 0 , VE , " level " } ,
{ " 5.1 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_5_1 } , 0 , 0 , VE , " level " } ,
{ " 5.2 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_5_2 } , 0 , 0 , VE , " level " } ,
{ " 6.0 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_6 } , 0 , 0 , VE , " level " } ,
{ " 6.1 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_6_1 } , 0 , 0 , VE , " level " } ,
{ " 6.2 " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_LEVEL_6_2 } , 0 , 0 , VE , " level " } ,
{ " quality " , " Set the encoding quality " , OFFSET ( quality ) , AV_OPT_TYPE_INT , { . i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED } , AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY , AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED , VE , " quality " } ,
{ " balanced " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED } , 0 , 0 , VE , " quality " } ,
{ " speed " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED } , 0 , 0 , VE , " quality " } ,
{ " quality " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY } , 0 , 0 , VE , " quality " } ,
{ " rc " , " Set the rate control mode " , OFFSET ( rate_control_mode ) , AV_OPT_TYPE_INT , { . i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN } , AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN , AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR , VE , " rc " } ,
{ " cqp " , " Constant Quantization Parameter " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP } , 0 , 0 , VE , " rc " } ,
{ " cbr " , " Constant Bitrate " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR } , 0 , 0 , VE , " rc " } ,
{ " vbr_peak " , " Peak Contrained Variable Bitrate " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR } , 0 , 0 , VE , " rc " } ,
{ " vbr_latency " , " Latency Constrained Variable Bitrate " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR } , 0 , 0 , VE , " rc " } ,
{ " qvbr " , " Quality Variable Bitrate " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_QUALITY_VBR } , 0 , 0 , VE , " rc " } ,
{ " hqvbr " , " High Quality Variable Bitrate " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_HIGH_QUALITY_VBR } , 0 , 0 , VE , " rc " } ,
{ " hqcbr " , " High Quality Constant Bitrate " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR } , 0 , 0 , VE , " rc " } ,
{ " qvbr_quality_level " , " Sets the QVBR quality level " , OFFSET ( qvbr_quality_level ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 51 , VE } ,
{ " header_insertion_mode " , " Set header insertion mode " , OFFSET ( header_insertion_mode ) , AV_OPT_TYPE_INT , { . i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE } , AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE , AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED , VE , " hdrmode " } ,
{ " none " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE } , 0 , 0 , VE , " hdrmode " } ,
{ " gop " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_GOP_ALIGNED } , 0 , 0 , VE , " hdrmode " } ,
{ " idr " , " " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED } , 0 , 0 , VE , " hdrmode " } ,
{ " high_motion_quality_boost_enable " , " Enable High motion quality boost mode " , OFFSET ( hw_high_motion_quality_boost ) , AV_OPT_TYPE_BOOL , { . i64 = - 1 } , - 1 , 1 , VE } ,
{ " gops_per_idr " , " GOPs per IDR 0-no IDR will be inserted " , OFFSET ( gops_per_idr ) , AV_OPT_TYPE_INT , { . i64 = 1 } , 0 , INT_MAX , VE } ,
{ " preencode " , " Enable preencode " , OFFSET ( preencode ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , VE } ,
{ " vbaq " , " Enable VBAQ " , OFFSET ( enable_vbaq ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , VE } ,
{ " enforce_hrd " , " Enforce HRD " , OFFSET ( enforce_hrd ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , VE } ,
{ " filler_data " , " Filler Data Enable " , OFFSET ( filler_data ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , VE } ,
{ " max_au_size " , " Maximum Access Unit Size for rate control (in bits) " , OFFSET ( max_au_size ) , AV_OPT_TYPE_INT , { . i64 = 0 } , 0 , INT_MAX , VE } ,
{ " min_qp_i " , " min quantization parameter for I-frame " , OFFSET ( min_qp_i ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 51 , VE } ,
{ " max_qp_i " , " max quantization parameter for I-frame " , OFFSET ( max_qp_i ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 51 , VE } ,
{ " min_qp_p " , " min quantization parameter for P-frame " , OFFSET ( min_qp_p ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 51 , VE } ,
{ " max_qp_p " , " max quantization parameter for P-frame " , OFFSET ( max_qp_p ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 51 , VE } ,
{ " qp_p " , " quantization parameter for P-frame " , OFFSET ( qp_p ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 51 , VE } ,
{ " qp_i " , " quantization parameter for I-frame " , OFFSET ( qp_i ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 51 , VE } ,
{ " skip_frame " , " Rate Control Based Frame Skip " , OFFSET ( skip_frame ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , VE } ,
{ " me_half_pel " , " Enable ME Half Pixel " , OFFSET ( me_half_pel ) , AV_OPT_TYPE_BOOL , { . i64 = 1 } , 0 , 1 , VE } ,
{ " me_quarter_pel " , " Enable ME Quarter Pixel " , OFFSET ( me_quarter_pel ) , AV_OPT_TYPE_BOOL , { . i64 = 1 } , 0 , 1 , VE } ,
{ " aud " , " Inserts AU Delimiter NAL unit " , OFFSET ( aud ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , VE } ,
{ " log_to_dbg " , " Enable AMF logging to debug output " , OFFSET ( log_to_dbg ) , AV_OPT_TYPE_BOOL , { . i64 = 0 } , 0 , 1 , VE } ,
//Pre Analysis options
{ " preanalysis " , " Enable preanalysis " , OFFSET ( preanalysis ) , AV_OPT_TYPE_BOOL , { . i64 = - 1 } , - 1 , 1 , VE } ,
{ " pa_activity_type " , " Set the type of activity analysis " , OFFSET ( pa_activity_type ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , AMF_PA_ACTIVITY_YUV , VE , " activity_type " } ,
{ " y " , " activity y " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_ACTIVITY_Y } , 0 , 0 , VE , " activity_type " } ,
{ " yuv " , " activity yuv " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_ACTIVITY_YUV } , 0 , 0 , VE , " activity_type " } ,
{ " pa_scene_change_detection_enable " , " Enable scene change detection " , OFFSET ( pa_scene_change_detection ) , AV_OPT_TYPE_BOOL , { . i64 = - 1 } , - 1 , 1 , VE } ,
{ " pa_scene_change_detection_sensitivity " , " Set the sensitivity of scene change detection " , OFFSET ( pa_scene_change_detection_sensitivity ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_HIGH , VE , " scene_change_sensitivity " } ,
{ " low " , " low scene change dectection sensitivity " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_LOW } , 0 , 0 , VE , " scene_change_sensitivity " } ,
{ " medium " , " medium scene change dectection sensitivity " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_MEDIUM } , 0 , 0 , VE , " scene_change_sensitivity " } ,
{ " high " , " high scene change dectection sensitivity " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY_HIGH } , 0 , 0 , VE , " scene_change_sensitivity " } ,
{ " pa_static_scene_detection_enable " , " Enable static scene detection " , OFFSET ( pa_static_scene_detection ) , AV_OPT_TYPE_BOOL , { . i64 = - 1 } , - 1 , 1 , VE } ,
{ " pa_static_scene_detection_sensitivity " , " Set the sensitivity of static scene detection " , OFFSET ( pa_static_scene_detection_sensitivity ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_HIGH , VE , " static_scene_sensitivity " } ,
{ " low " , " low static scene dectection sensitivity " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_LOW } , 0 , 0 , VE , " static_scene_sensitivity " } ,
{ " medium " , " medium static scene dectection sensitivity " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_MEDIUM } , 0 , 0 , VE , " static_scene_sensitivity " } ,
{ " high " , " high static scene dectection sensitivity " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY_HIGH } , 0 , 0 , VE , " static_scene_sensitivity " } ,
{ " pa_initial_qp_after_scene_change " , " The QP value that is used immediately after a scene change " , OFFSET ( pa_initial_qp ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 51 , VE } ,
{ " pa_max_qp_before_force_skip " , " The QP threshold to allow a skip frame " , OFFSET ( pa_max_qp ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 51 , VE } ,
{ " pa_caq_strength " , " Content Adaptive Quantization strength " , OFFSET ( pa_caq_strength ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , AMF_PA_CAQ_STRENGTH_HIGH , VE , " caq_strength " } ,
{ " low " , " low Content Adaptive Quantization strength " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_CAQ_STRENGTH_LOW } , 0 , 0 , VE , " caq_strength " } ,
{ " medium " , " medium Content Adaptive Quantization strength " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_CAQ_STRENGTH_MEDIUM } , 0 , 0 , VE , " caq_strength " } ,
{ " high " , " high Content Adaptive Quantization strength " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_CAQ_STRENGTH_HIGH } , 0 , 0 , VE , " caq_strength " } ,
{ " pa_frame_sad_enable " , " Enable Frame SAD algorithm " , OFFSET ( pa_frame_sad ) , AV_OPT_TYPE_BOOL , { . i64 = - 1 } , - 1 , 1 , VE } ,
{ " pa_ltr_enable " , " Enable long term reference frame management " , OFFSET ( pa_ltr ) , AV_OPT_TYPE_BOOL , { . i64 = - 1 } , - 1 , 1 , VE } ,
{ " pa_lookahead_buffer_depth " , " Sets the PA lookahead buffer size " , OFFSET ( pa_lookahead_buffer_depth ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , MAX_LOOKAHEAD_DEPTH , VE } ,
{ " pa_paq_mode " , " Sets the perceptual adaptive quantization mode " , OFFSET ( pa_paq_mode ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , AMF_PA_PAQ_MODE_CAQ , VE , " paq_mode " } ,
{ " none " , " no perceptual adaptive quantization " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_PAQ_MODE_NONE } , 0 , 0 , VE , " paq_mode " } ,
{ " caq " , " caq perceptual adaptive quantization " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_PAQ_MODE_CAQ } , 0 , 0 , VE , " paq_mode " } ,
{ " pa_taq_mode " , " Sets the temporal adaptive quantization mode " , OFFSET ( pa_taq_mode ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , AMF_PA_TAQ_MODE_2 , VE , " taq_mode " } ,
{ " none " , " no temporal adaptive quantization " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_TAQ_MODE_NONE } , 0 , 0 , VE , " taq_mode " } ,
{ " 1 " , " temporal adaptive quantization mode 1 " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_TAQ_MODE_1 } , 0 , 0 , VE , " taq_mode " } ,
{ " 2 " , " temporal adaptive quantization mode 2 " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_TAQ_MODE_2 } , 0 , 0 , VE , " taq_mode " } ,
{ " pa_high_motion_quality_boost_mode " , " Sets the PA high motion quality boost mode " , OFFSET ( pa_high_motion_quality_boost_mode ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_AUTO , VE , " high_motion_quality_boost_mode " } ,
{ " none " , " no high motion quality boost " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_NONE } , 0 , 0 , VE , " high_motion_quality_boost_mode " } ,
{ " auto " , " auto high motion quality boost " , 0 , AV_OPT_TYPE_CONST , { . i64 = AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_AUTO } , 0 , 0 , VE , " high_motion_quality_boost_mode " } ,
{ NULL }
} ;
static av_cold int amf_encode_init_hevc ( AVCodecContext * avctx )
{
int ret = 0 ;
AMF_RESULT res = AMF_OK ;
AmfContext * ctx = avctx - > priv_data ;
AMFVariantStruct var = { 0 } ;
amf_int64 profile = 0 ;
amf_int64 profile_level = 0 ;
AMFBuffer * buffer ;
AMFGuid guid ;
AMFRate framerate ;
AMFSize framesize = AMFConstructSize ( avctx - > width , avctx - > height ) ;
int deblocking_filter = ( avctx - > flags & AV_CODEC_FLAG_LOOP_FILTER ) ? 1 : 0 ;
if ( avctx - > framerate . num > 0 & & avctx - > framerate . den > 0 ) {
framerate = AMFConstructRate ( avctx - > framerate . num , avctx - > framerate . den ) ;
} else {
FF_DISABLE_DEPRECATION_WARNINGS
framerate = AMFConstructRate ( avctx - > time_base . den , avctx - > time_base . num
# if FF_API_TICKS_PER_FRAME
* avctx - > ticks_per_frame
# endif
) ;
FF_ENABLE_DEPRECATION_WARNINGS
}
if ( ( ret = ff_amf_encode_init ( avctx ) ) < 0 )
return ret ;
// init static parameters
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_USAGE , ctx - > usage ) ;
AMF_ASSIGN_PROPERTY_SIZE ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_FRAMESIZE , framesize ) ;
AMF_ASSIGN_PROPERTY_RATE ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_FRAMERATE , framerate ) ;
switch ( avctx - > profile ) {
case AV_PROFILE_HEVC_MAIN :
profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN ;
break ;
default :
break ;
}
if ( profile = = 0 ) {
profile = ctx - > profile ;
}
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_PROFILE , profile ) ;
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_TIER , ctx - > tier ) ;
profile_level = avctx - > level ;
if ( profile_level = = AV_LEVEL_UNKNOWN ) {
profile_level = ctx - > level ;
}
if ( profile_level ! = 0 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_PROFILE_LEVEL , profile_level ) ;
}
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET , ctx - > quality ) ;
// Maximum Reference Frames
if ( avctx - > refs ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_MAX_NUM_REFRAMES , avctx - > refs ) ;
}
// Aspect Ratio
if ( avctx - > sample_aspect_ratio . den & & avctx - > sample_aspect_ratio . num ) {
AMFRatio ratio = AMFConstructRatio ( avctx - > sample_aspect_ratio . num , avctx - > sample_aspect_ratio . den ) ;
AMF_ASSIGN_PROPERTY_RATIO ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO , ratio ) ;
}
// Picture control properties
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR , ctx - > gops_per_idr ) ;
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_GOP_SIZE , avctx - > gop_size ) ;
if ( avctx - > slices > 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_SLICES_PER_FRAME , avctx - > slices ) ;
}
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_DE_BLOCKING_FILTER_DISABLE , deblocking_filter ) ;
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE , ctx - > header_insertion_mode ) ;
// Rate control
// autodetect rate control method
if ( ctx - > rate_control_mode = = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN ) {
if ( ctx - > min_qp_i ! = - 1 | | ctx - > max_qp_i ! = - 1 | |
ctx - > min_qp_p ! = - 1 | | ctx - > max_qp_p ! = - 1 | |
ctx - > qp_i ! = - 1 | | ctx - > qp_p ! = - 1 ) {
ctx - > rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP ;
av_log ( ctx , AV_LOG_DEBUG , " Rate control turned to CQP \n " ) ;
} else if ( avctx - > rc_max_rate > 0 ) {
ctx - > rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR ;
av_log ( ctx , AV_LOG_DEBUG , " Rate control turned to Peak VBR \n " ) ;
} else {
ctx - > rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR ;
av_log ( ctx , AV_LOG_DEBUG , " Rate control turned to CBR \n " ) ;
}
}
// Pre-Pass, Pre-Analysis, Two-Pass
if ( ctx - > rate_control_mode = = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_PREENCODE_ENABLE , 0 ) ;
if ( ctx - > preencode )
av_log ( ctx , AV_LOG_WARNING , " Preencode is not supported by cqp Rate Control Method, automatically disabled \n " ) ;
}
else {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_PREENCODE_ENABLE , ctx - > preencode ) ;
}
if ( ctx - > rate_control_mode = = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_QUALITY_VBR ) {
if ( ctx - > qvbr_quality_level ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_QVBR_QUALITY_LEVEL , ctx - > qvbr_quality_level ) ;
}
}
if ( ctx - > hw_high_motion_quality_boost ! = - 1 ) {
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_HIGH_MOTION_QUALITY_BOOST_ENABLE , ( ( ctx - > hw_high_motion_quality_boost = = 0 ) ? false : true ) ) ;
}
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD , ctx - > rate_control_mode ) ;
if ( avctx - > rc_buffer_size ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_VBV_BUFFER_SIZE , avctx - > rc_buffer_size ) ;
if ( avctx - > rc_initial_buffer_occupancy ! = 0 ) {
int amf_buffer_fullness = avctx - > rc_initial_buffer_occupancy * 64 / avctx - > rc_buffer_size ;
if ( amf_buffer_fullness > 64 )
amf_buffer_fullness = 64 ;
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_INITIAL_VBV_BUFFER_FULLNESS , amf_buffer_fullness ) ;
}
}
if ( ctx - > rate_control_mode = = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP ) {
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ , false ) ;
if ( ctx - > enable_vbaq )
av_log ( ctx , AV_LOG_WARNING , " VBAQ is not supported by cqp Rate Control Method, automatically disabled \n " ) ;
} else {
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ , ! ! ctx - > enable_vbaq ) ;
}
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_MOTION_HALF_PIXEL , ctx - > me_half_pel ) ;
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_MOTION_QUARTERPIXEL , ctx - > me_quarter_pel ) ;
// init dynamic rate control params
if ( ctx - > max_au_size )
ctx - > enforce_hrd = 1 ;
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_ENFORCE_HRD , ctx - > enforce_hrd ) ;
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_FILLER_DATA_ENABLE , ctx - > filler_data ) ;
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_TARGET_BITRATE , avctx - > bit_rate ) ;
if ( ctx - > rate_control_mode = = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE , avctx - > bit_rate ) ;
}
if ( avctx - > rc_max_rate ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE , avctx - > rc_max_rate ) ;
} else if ( ctx - > rate_control_mode = = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR ) {
av_log ( ctx , AV_LOG_WARNING , " rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set \n " ) ;
}
if ( ctx - > preanalysis ! = - 1 ) {
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_PRE_ANALYSIS_ENABLE , ! ! ( ( ctx - > preanalysis = = 0 ) ? false : true ) ) ;
}
res = ctx - > encoder - > pVtbl - > GetProperty ( ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_PRE_ANALYSIS_ENABLE , & var ) ;
if ( ( int ) var . int64Value )
{
if ( ctx - > pa_activity_type ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_PA_ACTIVITY_TYPE , ctx - > pa_activity_type ) ;
}
if ( ctx - > pa_scene_change_detection ! = - 1 ) {
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_PA_SCENE_CHANGE_DETECTION_ENABLE , ( ( ctx - > pa_scene_change_detection = = 0 ) ? false : true ) ) ;
}
if ( ctx - > pa_scene_change_detection_sensitivity ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY , ctx - > pa_scene_change_detection_sensitivity ) ;
}
if ( ctx - > pa_static_scene_detection ! = - 1 ) {
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_PA_STATIC_SCENE_DETECTION_ENABLE , ( ( ctx - > pa_static_scene_detection = = 0 ) ? false : true ) ) ;
}
if ( ctx - > pa_static_scene_detection_sensitivity ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY , ctx - > pa_static_scene_detection_sensitivity ) ;
}
if ( ctx - > pa_initial_qp ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_PA_INITIAL_QP_AFTER_SCENE_CHANGE , ctx - > pa_initial_qp ) ;
}
if ( ctx - > pa_max_qp ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_PA_MAX_QP_BEFORE_FORCE_SKIP , ctx - > pa_max_qp ) ;
}
if ( ctx - > pa_caq_strength ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_PA_CAQ_STRENGTH , ctx - > pa_caq_strength ) ;
}
if ( ctx - > pa_frame_sad ! = - 1 ) {
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_PA_FRAME_SAD_ENABLE , ( ( ctx - > pa_frame_sad = = 0 ) ? false : true ) ) ;
}
if ( ctx - > pa_paq_mode ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_PA_PAQ_MODE , ctx - > pa_paq_mode ) ;
}
if ( ctx - > pa_taq_mode ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_PA_TAQ_MODE , ctx - > pa_taq_mode ) ;
}
if ( ctx - > pa_ltr ! = - 1 ) {
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_PA_LTR_ENABLE , ( ( ctx - > pa_ltr = = 0 ) ? false : true ) ) ;
}
if ( ctx - > pa_lookahead_buffer_depth ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_PA_LOOKAHEAD_BUFFER_DEPTH , ctx - > pa_lookahead_buffer_depth ) ;
}
if ( ctx - > pa_high_motion_quality_boost_mode ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE , ctx - > pa_high_motion_quality_boost_mode ) ;
}
}
// init encoder
res = ctx - > encoder - > pVtbl - > Init ( ctx - > encoder , ctx - > format , avctx - > width , avctx - > height ) ;
AMF_RETURN_IF_FALSE ( ctx , res = = AMF_OK , AVERROR_BUG , " encoder->Init() failed with error %d \n " , res ) ;
// init dynamic picture control params
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_MAX_AU_SIZE , ctx - > max_au_size ) ;
if ( ctx - > min_qp_i ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_MIN_QP_I , ctx - > min_qp_i ) ;
} else if ( avctx - > qmin ! = - 1 ) {
int qval = avctx - > qmin > 51 ? 51 : avctx - > qmin ;
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_MIN_QP_I , qval ) ;
}
if ( ctx - > max_qp_i ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_MAX_QP_I , ctx - > max_qp_i ) ;
} else if ( avctx - > qmax ! = - 1 ) {
int qval = avctx - > qmax > 51 ? 51 : avctx - > qmax ;
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_MAX_QP_I , qval ) ;
}
if ( ctx - > min_qp_p ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_MIN_QP_P , ctx - > min_qp_p ) ;
} else if ( avctx - > qmin ! = - 1 ) {
int qval = avctx - > qmin > 51 ? 51 : avctx - > qmin ;
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_MIN_QP_P , qval ) ;
}
if ( ctx - > max_qp_p ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_MAX_QP_P , ctx - > max_qp_p ) ;
} else if ( avctx - > qmax ! = - 1 ) {
int qval = avctx - > qmax > 51 ? 51 : avctx - > qmax ;
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_MAX_QP_P , qval ) ;
}
if ( ctx - > qp_p ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_QP_P , ctx - > qp_p ) ;
}
if ( ctx - > qp_i ! = - 1 ) {
AMF_ASSIGN_PROPERTY_INT64 ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_QP_I , ctx - > qp_i ) ;
}
AMF_ASSIGN_PROPERTY_BOOL ( res , ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_SKIP_FRAME_ENABLE , ctx - > skip_frame ) ;
// fill extradata
res = AMFVariantInit ( & var ) ;
AMF_RETURN_IF_FALSE ( ctx , res = = AMF_OK , AVERROR_BUG , " AMFVariantInit() failed with error %d \n " , res ) ;
res = ctx - > encoder - > pVtbl - > GetProperty ( ctx - > encoder , AMF_VIDEO_ENCODER_HEVC_EXTRADATA , & var ) ;
AMF_RETURN_IF_FALSE ( ctx , res = = AMF_OK , AVERROR_BUG , " GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) failed with error %d \n " , res ) ;
AMF_RETURN_IF_FALSE ( ctx , var . pInterface ! = NULL , AVERROR_BUG , " GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) returned NULL \n " ) ;
guid = IID_AMFBuffer ( ) ;
res = var . pInterface - > pVtbl - > QueryInterface ( var . pInterface , & guid , ( void * * ) & buffer ) ; // query for buffer interface
if ( res ! = AMF_OK ) {
var . pInterface - > pVtbl - > Release ( var . pInterface ) ;
}
AMF_RETURN_IF_FALSE ( ctx , res = = AMF_OK , AVERROR_BUG , " QueryInterface(IID_AMFBuffer) failed with error %d \n " , res ) ;
avctx - > extradata_size = ( int ) buffer - > pVtbl - > GetSize ( buffer ) ;
avctx - > extradata = av_mallocz ( avctx - > extradata_size + AV_INPUT_BUFFER_PADDING_SIZE ) ;
if ( ! avctx - > extradata ) {
buffer - > pVtbl - > Release ( buffer ) ;
var . pInterface - > pVtbl - > Release ( var . pInterface ) ;
return AVERROR ( ENOMEM ) ;
}
memcpy ( avctx - > extradata , buffer - > pVtbl - > GetNative ( buffer ) , avctx - > extradata_size ) ;
buffer - > pVtbl - > Release ( buffer ) ;
var . pInterface - > pVtbl - > Release ( var . pInterface ) ;
return 0 ;
}
static const FFCodecDefault defaults [ ] = {
{ " refs " , " -1 " } ,
{ " aspect " , " 0 " } ,
{ " b " , " 2M " } ,
{ " g " , " 250 " } ,
{ " slices " , " 1 " } ,
{ " qmin " , " -1 " } ,
{ " qmax " , " -1 " } ,
{ NULL } ,
} ;
static const AVClass hevc_amf_class = {
. class_name = " hevc_amf " ,
. item_name = av_default_item_name ,
. option = options ,
. version = LIBAVUTIL_VERSION_INT ,
} ;
const FFCodec ff_hevc_amf_encoder = {
. p . name = " hevc_amf " ,
CODEC_LONG_NAME ( " AMD AMF HEVC encoder " ) ,
. p . type = AVMEDIA_TYPE_VIDEO ,
. p . id = AV_CODEC_ID_HEVC ,
. init = amf_encode_init_hevc ,
FF_CODEC_RECEIVE_PACKET_CB ( ff_amf_receive_packet ) ,
. close = ff_amf_encode_close ,
. priv_data_size = sizeof ( AmfContext ) ,
. p . priv_class = & hevc_amf_class ,
. defaults = defaults ,
. p . capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
AV_CODEC_CAP_DR1 ,
. caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
FF_CODEC_CAP_INIT_CLEANUP ,
. p . pix_fmts = ff_amf_pix_fmts ,
. p . wrapper_name = " amf " ,
. hw_configs = ff_amfenc_hw_configs ,
} ;