2017-08-24 02:16:28 +00:00
/*
2017-11-11 17:46:24 +00:00
* This file is part of FFmpeg .
2017-08-24 02:16:28 +00:00
*
2017-11-11 17:46:24 +00:00
* FFmpeg is free software ; you can redistribute it and / or
2017-08-24 02:16:28 +00:00
* 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 .
*
2017-11-11 17:46:24 +00:00
* FFmpeg is distributed in the hope that it will be useful ,
2017-08-24 02:16:28 +00:00
* 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
2017-11-11 17:46:24 +00:00
* License along with FFmpeg ; if not , write to the Free Software
2017-08-24 02:16:28 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
/**
* * @ file
* * Hardware accelerated common filters based on Intel Quick Sync Video VPP
* */
# include <float.h>
# include "libavutil/opt.h"
# include "libavutil/eval.h"
2021-08-01 23:06:25 +00:00
# include "libavutil/hwcontext.h"
2022-01-07 07:01:31 +00:00
# include "libavutil/hwcontext_qsv.h"
2017-08-24 02:16:28 +00:00
# include "libavutil/pixdesc.h"
2018-04-04 09:51:30 +00:00
# include "libavutil/mathematics.h"
2017-08-24 02:16:28 +00:00
# include "formats.h"
# include "internal.h"
# include "avfilter.h"
2021-03-31 02:07:44 +00:00
# include "filters.h"
2017-08-24 02:16:28 +00:00
# include "qsvvpp.h"
lavf/vf_vpp_qsv: add support for QSV transpose filter
Add transpose support for qsv_vpp with rotate and hflip:
- rotate: [0, 3] support clockwise rotation of 0, 90, 180, 270;
- hflip: [0, 1] support horizontal flip;
Configure with:
{"cclock_hflip","clock","cclock","clock_hflip","reversal","hflip","vflip"}
CMD:
ffmpeg -hwaccel qsv -c:v h264_qsv -i input.h264
-vf 'format=qsv,vpp_qsv=transpose=clock' -c:v h264_qsv output.h264
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -c:v h264_qsv -i input.h264
-vf 'hwupload=extra_hw_frames=64,format=qsv,vpp_qsv=transpose=cclock_hflip'
-f rawvideo -pix_fmt nv12 ./transpose.yuv
Signed-off-by: Linjie Fu <linjie.fu@intel.com>
Signed-off-by: Zhong Li <zhong.li@intel.com>
2019-07-10 17:57:46 +00:00
# include "transpose.h"
2017-08-24 02:16:28 +00:00
# define OFFSET(x) offsetof(VPPContext, x)
2017-11-12 17:07:45 +00:00
# define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM)
2017-08-24 02:16:28 +00:00
/* number of video enhancement filters */
2021-08-04 00:24:47 +00:00
# define ENH_FILTERS_COUNT (8)
2017-08-24 02:16:28 +00:00
typedef struct VPPContext {
const AVClass * class ;
QSVVPPContext * qsv ;
/* Video Enhancement Algorithms */
mfxExtVPPDeinterlacing deinterlace_conf ;
mfxExtVPPFrameRateConversion frc_conf ;
mfxExtVPPDenoise denoise_conf ;
mfxExtVPPDetail detail_conf ;
mfxExtVPPProcAmp procamp_conf ;
lavf/vf_vpp_qsv: add support for QSV transpose filter
Add transpose support for qsv_vpp with rotate and hflip:
- rotate: [0, 3] support clockwise rotation of 0, 90, 180, 270;
- hflip: [0, 1] support horizontal flip;
Configure with:
{"cclock_hflip","clock","cclock","clock_hflip","reversal","hflip","vflip"}
CMD:
ffmpeg -hwaccel qsv -c:v h264_qsv -i input.h264
-vf 'format=qsv,vpp_qsv=transpose=clock' -c:v h264_qsv output.h264
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -c:v h264_qsv -i input.h264
-vf 'hwupload=extra_hw_frames=64,format=qsv,vpp_qsv=transpose=cclock_hflip'
-f rawvideo -pix_fmt nv12 ./transpose.yuv
Signed-off-by: Linjie Fu <linjie.fu@intel.com>
Signed-off-by: Zhong Li <zhong.li@intel.com>
2019-07-10 17:57:46 +00:00
mfxExtVPPRotation rotation_conf ;
mfxExtVPPMirroring mirroring_conf ;
2021-02-24 01:41:58 +00:00
mfxExtVPPScaling scale_conf ;
2017-08-24 02:16:28 +00:00
2023-01-09 07:12:05 +00:00
/**
* New dimensions . Special values are :
* 0 = original width / height
* - 1 = keep original aspect
*/
2017-08-24 02:16:28 +00:00
int out_width ;
int out_height ;
2019-05-31 00:44:47 +00:00
/**
* Output sw format . AV_PIX_FMT_NONE for no conversion .
*/
enum AVPixelFormat out_format ;
2017-08-24 02:16:28 +00:00
AVRational framerate ; /* target framerate */
int use_frc ; /* use framerate conversion */
int deinterlace ; /* deinterlace mode : 0=off, 1=bob, 2=advanced */
int denoise ; /* Enable Denoise algorithm. Value [0, 100] */
int detail ; /* Enable Detail Enhancement algorithm. */
/* Level is the optional, value [0, 100] */
int use_crop ; /* 1 = use crop; 0=none */
int crop_w ;
int crop_h ;
int crop_x ;
int crop_y ;
lavf/vf_vpp_qsv: add support for QSV transpose filter
Add transpose support for qsv_vpp with rotate and hflip:
- rotate: [0, 3] support clockwise rotation of 0, 90, 180, 270;
- hflip: [0, 1] support horizontal flip;
Configure with:
{"cclock_hflip","clock","cclock","clock_hflip","reversal","hflip","vflip"}
CMD:
ffmpeg -hwaccel qsv -c:v h264_qsv -i input.h264
-vf 'format=qsv,vpp_qsv=transpose=clock' -c:v h264_qsv output.h264
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -c:v h264_qsv -i input.h264
-vf 'hwupload=extra_hw_frames=64,format=qsv,vpp_qsv=transpose=cclock_hflip'
-f rawvideo -pix_fmt nv12 ./transpose.yuv
Signed-off-by: Linjie Fu <linjie.fu@intel.com>
Signed-off-by: Zhong Li <zhong.li@intel.com>
2019-07-10 17:57:46 +00:00
int transpose ;
int rotate ; /* rotate angle : [0, 90, 180, 270] */
int hflip ; /* flip mode : 0 = off, 1 = HORIZONTAL flip */
2021-02-24 01:41:58 +00:00
int scale_mode ; /* scale mode : 0 = auto, 1 = low power, 2 = high quality */
2017-08-24 02:16:28 +00:00
/* param for the procamp */
int procamp ; /* enable procamp */
float hue ;
float saturation ;
float contrast ;
float brightness ;
char * cx , * cy , * cw , * ch ;
char * ow , * oh ;
2019-05-31 00:44:47 +00:00
char * output_format_str ;
2021-03-31 02:07:44 +00:00
int async_depth ;
int eof ;
2017-08-24 02:16:28 +00:00
} VPPContext ;
static const AVOption options [ ] = {
{ " deinterlace " , " deinterlace mode: 0=off, 1=bob, 2=advanced " , OFFSET ( deinterlace ) , AV_OPT_TYPE_INT , { . i64 = 0 } , 0 , MFX_DEINTERLACING_ADVANCED , . flags = FLAGS , " deinterlace " } ,
{ " bob " , " Bob deinterlace mode. " , 0 , AV_OPT_TYPE_CONST , { . i64 = MFX_DEINTERLACING_BOB } , . flags = FLAGS , " deinterlace " } ,
{ " advanced " , " Advanced deinterlace mode. " , 0 , AV_OPT_TYPE_CONST , { . i64 = MFX_DEINTERLACING_ADVANCED } , . flags = FLAGS , " deinterlace " } ,
{ " denoise " , " denoise level [0, 100] " , OFFSET ( denoise ) , AV_OPT_TYPE_INT , { . i64 = 0 } , 0 , 100 , . flags = FLAGS } ,
{ " detail " , " enhancement level [0, 100] " , OFFSET ( detail ) , AV_OPT_TYPE_INT , { . i64 = 0 } , 0 , 100 , . flags = FLAGS } ,
{ " framerate " , " output framerate " , OFFSET ( framerate ) , AV_OPT_TYPE_RATIONAL , { . dbl = 0.0 } , 0 , DBL_MAX , . flags = FLAGS } ,
{ " procamp " , " Enable ProcAmp " , OFFSET ( procamp ) , AV_OPT_TYPE_INT , { . i64 = 0 } , 0 , 1 , . flags = FLAGS } ,
{ " hue " , " ProcAmp hue " , OFFSET ( hue ) , AV_OPT_TYPE_FLOAT , { . dbl = 0.0 } , - 180.0 , 180.0 , . flags = FLAGS } ,
{ " saturation " , " ProcAmp saturation " , OFFSET ( saturation ) , AV_OPT_TYPE_FLOAT , { . dbl = 1.0 } , 0.0 , 10.0 , . flags = FLAGS } ,
{ " contrast " , " ProcAmp contrast " , OFFSET ( contrast ) , AV_OPT_TYPE_FLOAT , { . dbl = 1.0 } , 0.0 , 10.0 , . flags = FLAGS } ,
{ " brightness " , " ProcAmp brightness " , OFFSET ( brightness ) , AV_OPT_TYPE_FLOAT , { . dbl = 0.0 } , - 100.0 , 100.0 , . flags = FLAGS } ,
lavf/vf_vpp_qsv: add support for QSV transpose filter
Add transpose support for qsv_vpp with rotate and hflip:
- rotate: [0, 3] support clockwise rotation of 0, 90, 180, 270;
- hflip: [0, 1] support horizontal flip;
Configure with:
{"cclock_hflip","clock","cclock","clock_hflip","reversal","hflip","vflip"}
CMD:
ffmpeg -hwaccel qsv -c:v h264_qsv -i input.h264
-vf 'format=qsv,vpp_qsv=transpose=clock' -c:v h264_qsv output.h264
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -c:v h264_qsv -i input.h264
-vf 'hwupload=extra_hw_frames=64,format=qsv,vpp_qsv=transpose=cclock_hflip'
-f rawvideo -pix_fmt nv12 ./transpose.yuv
Signed-off-by: Linjie Fu <linjie.fu@intel.com>
Signed-off-by: Zhong Li <zhong.li@intel.com>
2019-07-10 17:57:46 +00:00
{ " transpose " , " set transpose direction " , OFFSET ( transpose ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 6 , FLAGS , " transpose " } ,
{ " cclock_hflip " , " rotate counter-clockwise with horizontal flip " , 0 , AV_OPT_TYPE_CONST , { . i64 = TRANSPOSE_CCLOCK_FLIP } , . flags = FLAGS , . unit = " transpose " } ,
{ " clock " , " rotate clockwise " , 0 , AV_OPT_TYPE_CONST , { . i64 = TRANSPOSE_CLOCK } , . flags = FLAGS , . unit = " transpose " } ,
{ " cclock " , " rotate counter-clockwise " , 0 , AV_OPT_TYPE_CONST , { . i64 = TRANSPOSE_CCLOCK } , . flags = FLAGS , . unit = " transpose " } ,
{ " clock_hflip " , " rotate clockwise with horizontal flip " , 0 , AV_OPT_TYPE_CONST , { . i64 = TRANSPOSE_CLOCK_FLIP } , . flags = FLAGS , . unit = " transpose " } ,
{ " reversal " , " rotate by half-turn " , 0 , AV_OPT_TYPE_CONST , { . i64 = TRANSPOSE_REVERSAL } , . flags = FLAGS , . unit = " transpose " } ,
{ " hflip " , " flip horizontally " , 0 , AV_OPT_TYPE_CONST , { . i64 = TRANSPOSE_HFLIP } , . flags = FLAGS , . unit = " transpose " } ,
{ " vflip " , " flip vertically " , 0 , AV_OPT_TYPE_CONST , { . i64 = TRANSPOSE_VFLIP } , . flags = FLAGS , . unit = " transpose " } ,
2020-03-17 21:46:36 +00:00
{ " cw " , " set the width crop area expression " , OFFSET ( cw ) , AV_OPT_TYPE_STRING , { . str = " iw " } , 0 , 0 , FLAGS } ,
{ " ch " , " set the height crop area expression " , OFFSET ( ch ) , AV_OPT_TYPE_STRING , { . str = " ih " } , 0 , 0 , FLAGS } ,
{ " cx " , " set the x crop area expression " , OFFSET ( cx ) , AV_OPT_TYPE_STRING , { . str = " (in_w-out_w)/2 " } , 0 , 0 , FLAGS } ,
{ " cy " , " set the y crop area expression " , OFFSET ( cy ) , AV_OPT_TYPE_STRING , { . str = " (in_h-out_h)/2 " } , 0 , 0 , FLAGS } ,
2017-08-24 02:16:28 +00:00
2023-01-09 07:12:05 +00:00
{ " w " , " Output video width(0=input video width, -1=keep input video aspect) " , OFFSET ( ow ) , AV_OPT_TYPE_STRING , { . str = " cw " } , 0 , 255 , . flags = FLAGS } ,
{ " width " , " Output video width(0=input video width, -1=keep input video aspect) " , OFFSET ( ow ) , AV_OPT_TYPE_STRING , { . str = " cw " } , 0 , 255 , . flags = FLAGS } ,
{ " h " , " Output video height(0=input video height, -1=keep input video aspect) " , OFFSET ( oh ) , AV_OPT_TYPE_STRING , { . str = " w*ch/cw " } , 0 , 255 , . flags = FLAGS } ,
{ " height " , " Output video height(0=input video height, -1=keep input video aspect) " , OFFSET ( oh ) , AV_OPT_TYPE_STRING , { . str = " w*ch/cw " } , 0 , 255 , . flags = FLAGS } ,
2019-05-31 00:44:47 +00:00
{ " format " , " Output pixel format " , OFFSET ( output_format_str ) , AV_OPT_TYPE_STRING , { . str = " same " } , . flags = FLAGS } ,
2021-03-31 02:07:44 +00:00
{ " async_depth " , " Internal parallelization depth, the higher the value the higher the latency. " , OFFSET ( async_depth ) , AV_OPT_TYPE_INT , { . i64 = 0 } , 0 , INT_MAX , . flags = FLAGS } ,
2022-11-28 04:43:21 +00:00
{ " scale_mode " , " scale & format conversion mode: 0=auto, 1=low power, 2=high quality " , OFFSET ( scale_mode ) , AV_OPT_TYPE_INT , { . i64 = MFX_SCALING_MODE_DEFAULT } , MFX_SCALING_MODE_DEFAULT , MFX_SCALING_MODE_QUALITY , . flags = FLAGS , " scale mode " } ,
2022-12-06 07:21:26 +00:00
{ " auto " , " auto mode " , 0 , AV_OPT_TYPE_CONST , { . i64 = MFX_SCALING_MODE_DEFAULT } , INT_MIN , INT_MAX , FLAGS , " scale mode " } ,
{ " low_power " , " low power mode " , 0 , AV_OPT_TYPE_CONST , { . i64 = MFX_SCALING_MODE_LOWPOWER } , INT_MIN , INT_MAX , FLAGS , " scale mode " } ,
{ " hq " , " high quality mode " , 0 , AV_OPT_TYPE_CONST , { . i64 = MFX_SCALING_MODE_QUALITY } , INT_MIN , INT_MAX , FLAGS , " scale mode " } ,
2017-08-24 02:16:28 +00:00
{ NULL }
} ;
static const char * const var_names [ ] = {
" iw " , " in_w " ,
" ih " , " in_h " ,
" ow " , " out_w " , " w " ,
" oh " , " out_h " , " h " ,
" cw " ,
" ch " ,
" cx " ,
" cy " ,
2023-01-09 07:12:03 +00:00
" a " , " dar " ,
" sar " ,
2017-08-24 02:16:28 +00:00
NULL
} ;
enum var_name {
2023-01-09 07:12:03 +00:00
VAR_IW , VAR_IN_W ,
VAR_IH , VAR_IN_H ,
VAR_OW , VAR_OUT_W , VAR_W ,
VAR_OH , VAR_OUT_H , VAR_H ,
VAR_CW ,
VAR_CH ,
VAR_CX ,
VAR_CY ,
VAR_A , VAR_DAR ,
VAR_SAR ,
2017-08-24 02:16:28 +00:00
VAR_VARS_NB
} ;
static int eval_expr ( AVFilterContext * ctx )
{
# define PASS_EXPR(e, s) {\
2023-01-09 07:12:04 +00:00
if ( s ) { \
ret = av_expr_parse ( & e , s , var_names , NULL , NULL , NULL , NULL , 0 , ctx ) ; \
if ( ret < 0 ) { \
av_log ( ctx , AV_LOG_ERROR , " Error when passing '%s'. \n " , s ) ; \
goto release ; \
} \
2017-08-24 02:16:28 +00:00
} \
}
2023-01-09 07:12:04 +00:00
# define CALC_EXPR(e, v, i, d) {\
if ( e ) \
i = v = av_expr_eval ( e , var_values , NULL ) ; \
else \
i = v = d ; \
2017-08-24 02:16:28 +00:00
}
VPPContext * vpp = ctx - > priv ;
double var_values [ VAR_VARS_NB ] = { NAN } ;
AVExpr * w_expr = NULL , * h_expr = NULL ;
AVExpr * cw_expr = NULL , * ch_expr = NULL ;
AVExpr * cx_expr = NULL , * cy_expr = NULL ;
int ret = 0 ;
PASS_EXPR ( cw_expr , vpp - > cw ) ;
PASS_EXPR ( ch_expr , vpp - > ch ) ;
PASS_EXPR ( w_expr , vpp - > ow ) ;
PASS_EXPR ( h_expr , vpp - > oh ) ;
PASS_EXPR ( cx_expr , vpp - > cx ) ;
PASS_EXPR ( cy_expr , vpp - > cy ) ;
2023-01-09 07:12:03 +00:00
var_values [ VAR_IW ] =
2017-08-24 02:16:28 +00:00
var_values [ VAR_IN_W ] = ctx - > inputs [ 0 ] - > w ;
2023-01-09 07:12:03 +00:00
var_values [ VAR_IH ] =
2017-08-24 02:16:28 +00:00
var_values [ VAR_IN_H ] = ctx - > inputs [ 0 ] - > h ;
2023-01-09 07:12:03 +00:00
var_values [ VAR_A ] = ( double ) var_values [ VAR_IN_W ] / var_values [ VAR_IN_H ] ;
var_values [ VAR_SAR ] = ctx - > inputs [ 0 ] - > sample_aspect_ratio . num ?
( double ) ctx - > inputs [ 0 ] - > sample_aspect_ratio . num / ctx - > inputs [ 0 ] - > sample_aspect_ratio . den : 1 ;
var_values [ VAR_DAR ] = var_values [ VAR_A ] * var_values [ VAR_SAR ] ;
2017-08-24 02:16:28 +00:00
/* crop params */
2023-01-09 07:12:04 +00:00
CALC_EXPR ( cw_expr , var_values [ VAR_CW ] , vpp - > crop_w , var_values [ VAR_IW ] ) ;
CALC_EXPR ( ch_expr , var_values [ VAR_CH ] , vpp - > crop_h , var_values [ VAR_IH ] ) ;
2017-08-24 02:16:28 +00:00
/* calc again in case cw is relative to ch */
2023-01-09 07:12:04 +00:00
CALC_EXPR ( cw_expr , var_values [ VAR_CW ] , vpp - > crop_w , var_values [ VAR_IW ] ) ;
2017-08-24 02:16:28 +00:00
CALC_EXPR ( w_expr ,
2023-01-09 07:12:03 +00:00
var_values [ VAR_OUT_W ] = var_values [ VAR_OW ] = var_values [ VAR_W ] ,
2023-01-09 07:12:04 +00:00
vpp - > out_width , var_values [ VAR_CW ] ) ;
2017-08-24 02:16:28 +00:00
CALC_EXPR ( h_expr ,
2023-01-09 07:12:03 +00:00
var_values [ VAR_OUT_H ] = var_values [ VAR_OH ] = var_values [ VAR_H ] ,
2023-01-09 07:12:04 +00:00
vpp - > out_height , var_values [ VAR_CH ] ) ;
2017-08-24 02:16:28 +00:00
/* calc again in case ow is relative to oh */
CALC_EXPR ( w_expr ,
2023-01-09 07:12:03 +00:00
var_values [ VAR_OUT_W ] = var_values [ VAR_OW ] = var_values [ VAR_W ] ,
2023-01-09 07:12:04 +00:00
vpp - > out_width , var_values [ VAR_CW ] ) ;
2017-08-24 02:16:28 +00:00
2023-01-09 07:12:04 +00:00
CALC_EXPR ( cx_expr , var_values [ VAR_CX ] , vpp - > crop_x , ( var_values [ VAR_IW ] - var_values [ VAR_OW ] ) / 2 ) ;
CALC_EXPR ( cy_expr , var_values [ VAR_CY ] , vpp - > crop_y , ( var_values [ VAR_IH ] - var_values [ VAR_OH ] ) / 2 ) ;
2017-08-24 02:16:28 +00:00
/* calc again in case cx is relative to cy */
2023-01-09 07:12:04 +00:00
CALC_EXPR ( cx_expr , var_values [ VAR_CX ] , vpp - > crop_x , ( var_values [ VAR_IW ] - var_values [ VAR_OW ] ) / 2 ) ;
2017-08-24 02:16:28 +00:00
2023-01-09 07:12:03 +00:00
if ( ( vpp - > crop_w ! = var_values [ VAR_IW ] ) | | ( vpp - > crop_h ! = var_values [ VAR_IH ] ) )
2017-08-24 02:16:28 +00:00
vpp - > use_crop = 1 ;
release :
av_expr_free ( w_expr ) ;
av_expr_free ( h_expr ) ;
av_expr_free ( cw_expr ) ;
av_expr_free ( ch_expr ) ;
av_expr_free ( cx_expr ) ;
av_expr_free ( cy_expr ) ;
# undef PASS_EXPR
# undef CALC_EXPR
return ret ;
}
2019-05-31 00:44:47 +00:00
static av_cold int vpp_init ( AVFilterContext * ctx )
{
VPPContext * vpp = ctx - > priv ;
if ( ! strcmp ( vpp - > output_format_str , " same " ) ) {
vpp - > out_format = AV_PIX_FMT_NONE ;
} else {
vpp - > out_format = av_get_pix_fmt ( vpp - > output_format_str ) ;
if ( vpp - > out_format = = AV_PIX_FMT_NONE ) {
av_log ( ctx , AV_LOG_ERROR , " Unrecognized output pixel format: %s \n " , vpp - > output_format_str ) ;
return AVERROR ( EINVAL ) ;
}
}
return 0 ;
}
2017-08-24 02:16:28 +00:00
static int config_input ( AVFilterLink * inlink )
{
AVFilterContext * ctx = inlink - > dst ;
VPPContext * vpp = ctx - > priv ;
int ret ;
2023-01-09 07:12:05 +00:00
int64_t ow , oh ;
2017-08-24 02:16:28 +00:00
if ( vpp - > framerate . den = = 0 | | vpp - > framerate . num = = 0 )
vpp - > framerate = inlink - > frame_rate ;
if ( av_cmp_q ( vpp - > framerate , inlink - > frame_rate ) )
vpp - > use_frc = 1 ;
ret = eval_expr ( ctx ) ;
if ( ret ! = 0 ) {
av_log ( ctx , AV_LOG_ERROR , " Fail to eval expr. \n " ) ;
return ret ;
}
2023-01-09 07:12:05 +00:00
ow = vpp - > out_width ;
oh = vpp - > out_height ;
/* sanity check params */
if ( ow < - 1 | | oh < - 1 ) {
av_log ( ctx , AV_LOG_ERROR , " Size values less than -1 are not acceptable. \n " ) ;
return AVERROR ( EINVAL ) ;
2017-08-24 02:16:28 +00:00
}
2023-01-09 07:12:05 +00:00
if ( ow = = - 1 & & oh = = - 1 )
vpp - > out_width = vpp - > out_height = 0 ;
if ( ! ( ow = vpp - > out_width ) )
ow = inlink - > w ;
if ( ! ( oh = vpp - > out_height ) )
oh = inlink - > h ;
if ( ow = = - 1 )
ow = av_rescale ( oh , inlink - > w , inlink - > h ) ;
if ( oh = = - 1 )
oh = av_rescale ( ow , inlink - > h , inlink - > w ) ;
if ( ow > INT_MAX | | oh > INT_MAX | |
( oh * inlink - > w ) > INT_MAX | |
( ow * inlink - > h ) > INT_MAX )
av_log ( ctx , AV_LOG_ERROR , " Rescaled value for width or height is too big. \n " ) ;
vpp - > out_width = ow ;
vpp - > out_height = oh ;
2017-08-24 02:16:28 +00:00
if ( vpp - > use_crop ) {
vpp - > crop_x = FFMAX ( vpp - > crop_x , 0 ) ;
vpp - > crop_y = FFMAX ( vpp - > crop_y , 0 ) ;
if ( vpp - > crop_w + vpp - > crop_x > inlink - > w )
vpp - > crop_x = inlink - > w - vpp - > crop_w ;
if ( vpp - > crop_h + vpp - > crop_y > inlink - > h )
vpp - > crop_y = inlink - > h - vpp - > crop_h ;
}
return 0 ;
}
2022-01-07 07:01:31 +00:00
static mfxStatus get_mfx_version ( const AVFilterContext * ctx , mfxVersion * mfx_version )
{
const AVFilterLink * inlink = ctx - > inputs [ 0 ] ;
AVBufferRef * device_ref ;
AVHWDeviceContext * device_ctx ;
AVQSVDeviceContext * device_hwctx ;
if ( inlink - > hw_frames_ctx ) {
AVHWFramesContext * frames_ctx = ( AVHWFramesContext * ) inlink - > hw_frames_ctx - > data ;
device_ref = frames_ctx - > device_ref ;
} else if ( ctx - > hw_device_ctx ) {
device_ref = ctx - > hw_device_ctx ;
} else {
// Unavailable hw context doesn't matter in pass-through mode,
// so don't error here but let runtime version checks fail by setting to 0.0
mfx_version - > Major = 0 ;
mfx_version - > Minor = 0 ;
return MFX_ERR_NONE ;
}
device_ctx = ( AVHWDeviceContext * ) device_ref - > data ;
device_hwctx = device_ctx - > hwctx ;
return MFXQueryVersion ( device_hwctx - > session , mfx_version ) ;
}
2017-08-24 02:16:28 +00:00
static int config_output ( AVFilterLink * outlink )
{
AVFilterContext * ctx = outlink - > src ;
VPPContext * vpp = ctx - > priv ;
QSVVPPParam param = { NULL } ;
QSVVPPCrop crop = { 0 } ;
mfxExtBuffer * ext_buf [ ENH_FILTERS_COUNT ] ;
2022-01-07 07:01:31 +00:00
mfxVersion mfx_version ;
2018-04-04 09:51:30 +00:00
AVFilterLink * inlink = ctx - > inputs [ 0 ] ;
2019-05-31 00:44:47 +00:00
enum AVPixelFormat in_format ;
2017-08-24 02:16:28 +00:00
outlink - > w = vpp - > out_width ;
outlink - > h = vpp - > out_height ;
outlink - > frame_rate = vpp - > framerate ;
2021-06-11 02:19:46 +00:00
outlink - > time_base = inlink - > time_base ;
2017-08-24 02:16:28 +00:00
param . filter_frame = NULL ;
param . num_ext_buf = 0 ;
param . ext_buf = ext_buf ;
2021-03-31 02:07:44 +00:00
param . async_depth = vpp - > async_depth ;
2017-08-24 02:16:28 +00:00
2022-01-07 07:01:31 +00:00
if ( get_mfx_version ( ctx , & mfx_version ) ! = MFX_ERR_NONE ) {
av_log ( ctx , AV_LOG_ERROR , " Failed to query mfx version. \n " ) ;
return AVERROR ( EINVAL ) ;
}
2019-05-31 00:44:47 +00:00
if ( inlink - > format = = AV_PIX_FMT_QSV ) {
if ( ! inlink - > hw_frames_ctx | | ! inlink - > hw_frames_ctx - > data )
return AVERROR ( EINVAL ) ;
else
in_format = ( ( AVHWFramesContext * ) inlink - > hw_frames_ctx - > data ) - > sw_format ;
} else
in_format = inlink - > format ;
2019-08-15 02:33:57 +00:00
if ( vpp - > out_format = = AV_PIX_FMT_NONE )
vpp - > out_format = in_format ;
param . out_sw_format = vpp - > out_format ;
2019-05-31 00:44:47 +00:00
2017-08-24 02:16:28 +00:00
if ( vpp - > use_crop ) {
crop . in_idx = 0 ;
crop . x = vpp - > crop_x ;
crop . y = vpp - > crop_y ;
crop . w = vpp - > crop_w ;
crop . h = vpp - > crop_h ;
param . num_crop = 1 ;
param . crop = & crop ;
}
2022-12-05 06:25:08 +00:00
# define INIT_MFX_EXTBUF(extbuf, id) do { \
memset ( & vpp - > extbuf , 0 , sizeof ( vpp - > extbuf ) ) ; \
vpp - > extbuf . Header . BufferId = id ; \
vpp - > extbuf . Header . BufferSz = sizeof ( vpp - > extbuf ) ; \
param . ext_buf [ param . num_ext_buf + + ] = ( mfxExtBuffer * ) & vpp - > extbuf ; \
} while ( 0 )
# define SET_MFX_PARAM_FIELD(extbuf, field, value) do { \
vpp - > extbuf . field = value ; \
} while ( 0 )
2017-08-24 02:16:28 +00:00
2022-12-05 06:25:08 +00:00
if ( vpp - > deinterlace ) {
INIT_MFX_EXTBUF ( deinterlace_conf , MFX_EXTBUFF_VPP_DEINTERLACING ) ;
SET_MFX_PARAM_FIELD ( deinterlace_conf , Mode , ( vpp - > deinterlace = = 1 ?
MFX_DEINTERLACING_BOB : MFX_DEINTERLACING_ADVANCED ) ) ;
2017-08-24 02:16:28 +00:00
}
if ( vpp - > use_frc ) {
2022-12-05 06:25:08 +00:00
INIT_MFX_EXTBUF ( frc_conf , MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION ) ;
SET_MFX_PARAM_FIELD ( frc_conf , Algorithm , MFX_FRCALGM_DISTRIBUTED_TIMESTAMP ) ;
2017-08-24 02:16:28 +00:00
}
if ( vpp - > denoise ) {
2022-12-05 06:25:08 +00:00
INIT_MFX_EXTBUF ( denoise_conf , MFX_EXTBUFF_VPP_DENOISE ) ;
SET_MFX_PARAM_FIELD ( denoise_conf , DenoiseFactor , vpp - > denoise ) ;
2017-08-24 02:16:28 +00:00
}
if ( vpp - > detail ) {
2022-12-05 06:25:08 +00:00
INIT_MFX_EXTBUF ( detail_conf , MFX_EXTBUFF_VPP_DETAIL ) ;
SET_MFX_PARAM_FIELD ( detail_conf , DetailFactor , vpp - > detail ) ;
2017-08-24 02:16:28 +00:00
}
if ( vpp - > procamp ) {
2022-12-05 06:25:08 +00:00
INIT_MFX_EXTBUF ( procamp_conf , MFX_EXTBUFF_VPP_PROCAMP ) ;
SET_MFX_PARAM_FIELD ( procamp_conf , Hue , vpp - > hue ) ;
SET_MFX_PARAM_FIELD ( procamp_conf , Saturation , vpp - > saturation ) ;
SET_MFX_PARAM_FIELD ( procamp_conf , Contrast , vpp - > contrast ) ;
SET_MFX_PARAM_FIELD ( procamp_conf , Brightness , vpp - > brightness ) ;
2017-08-24 02:16:28 +00:00
}
lavf/vf_vpp_qsv: add support for QSV transpose filter
Add transpose support for qsv_vpp with rotate and hflip:
- rotate: [0, 3] support clockwise rotation of 0, 90, 180, 270;
- hflip: [0, 1] support horizontal flip;
Configure with:
{"cclock_hflip","clock","cclock","clock_hflip","reversal","hflip","vflip"}
CMD:
ffmpeg -hwaccel qsv -c:v h264_qsv -i input.h264
-vf 'format=qsv,vpp_qsv=transpose=clock' -c:v h264_qsv output.h264
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -c:v h264_qsv -i input.h264
-vf 'hwupload=extra_hw_frames=64,format=qsv,vpp_qsv=transpose=cclock_hflip'
-f rawvideo -pix_fmt nv12 ./transpose.yuv
Signed-off-by: Linjie Fu <linjie.fu@intel.com>
Signed-off-by: Zhong Li <zhong.li@intel.com>
2019-07-10 17:57:46 +00:00
if ( vpp - > transpose > = 0 ) {
2022-05-22 12:19:11 +00:00
if ( QSV_RUNTIME_VERSION_ATLEAST ( mfx_version , 1 , 17 ) ) {
switch ( vpp - > transpose ) {
case TRANSPOSE_CCLOCK_FLIP :
vpp - > rotate = MFX_ANGLE_270 ;
vpp - > hflip = MFX_MIRRORING_HORIZONTAL ;
break ;
case TRANSPOSE_CLOCK :
vpp - > rotate = MFX_ANGLE_90 ;
vpp - > hflip = MFX_MIRRORING_DISABLED ;
break ;
case TRANSPOSE_CCLOCK :
vpp - > rotate = MFX_ANGLE_270 ;
vpp - > hflip = MFX_MIRRORING_DISABLED ;
break ;
case TRANSPOSE_CLOCK_FLIP :
vpp - > rotate = MFX_ANGLE_90 ;
vpp - > hflip = MFX_MIRRORING_HORIZONTAL ;
break ;
case TRANSPOSE_REVERSAL :
vpp - > rotate = MFX_ANGLE_180 ;
vpp - > hflip = MFX_MIRRORING_DISABLED ;
break ;
case TRANSPOSE_HFLIP :
vpp - > rotate = MFX_ANGLE_0 ;
vpp - > hflip = MFX_MIRRORING_HORIZONTAL ;
break ;
case TRANSPOSE_VFLIP :
vpp - > rotate = MFX_ANGLE_180 ;
vpp - > hflip = MFX_MIRRORING_HORIZONTAL ;
break ;
default :
av_log ( ctx , AV_LOG_ERROR , " Failed to set transpose mode to %d. \n " , vpp - > transpose ) ;
return AVERROR ( EINVAL ) ;
}
} else {
av_log ( ctx , AV_LOG_WARNING , " The QSV VPP transpose option is "
" not supported with this MSDK version. \n " ) ;
vpp - > transpose = 0 ;
lavf/vf_vpp_qsv: add support for QSV transpose filter
Add transpose support for qsv_vpp with rotate and hflip:
- rotate: [0, 3] support clockwise rotation of 0, 90, 180, 270;
- hflip: [0, 1] support horizontal flip;
Configure with:
{"cclock_hflip","clock","cclock","clock_hflip","reversal","hflip","vflip"}
CMD:
ffmpeg -hwaccel qsv -c:v h264_qsv -i input.h264
-vf 'format=qsv,vpp_qsv=transpose=clock' -c:v h264_qsv output.h264
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -c:v h264_qsv -i input.h264
-vf 'hwupload=extra_hw_frames=64,format=qsv,vpp_qsv=transpose=cclock_hflip'
-f rawvideo -pix_fmt nv12 ./transpose.yuv
Signed-off-by: Linjie Fu <linjie.fu@intel.com>
Signed-off-by: Zhong Li <zhong.li@intel.com>
2019-07-10 17:57:46 +00:00
}
}
if ( vpp - > rotate ) {
2022-05-22 12:19:11 +00:00
if ( QSV_RUNTIME_VERSION_ATLEAST ( mfx_version , 1 , 17 ) ) {
2022-12-05 06:25:08 +00:00
INIT_MFX_EXTBUF ( rotation_conf , MFX_EXTBUFF_VPP_ROTATION ) ;
SET_MFX_PARAM_FIELD ( rotation_conf , Angle , vpp - > rotate ) ;
2022-05-22 12:19:11 +00:00
if ( MFX_ANGLE_90 = = vpp - > rotate | | MFX_ANGLE_270 = = vpp - > rotate ) {
FFSWAP ( int , vpp - > out_width , vpp - > out_height ) ;
FFSWAP ( int , outlink - > w , outlink - > h ) ;
av_log ( ctx , AV_LOG_DEBUG , " Swap width and height for clock/cclock rotation. \n " ) ;
}
} else {
av_log ( ctx , AV_LOG_WARNING , " The QSV VPP rotate option is "
" not supported with this MSDK version. \n " ) ;
vpp - > rotate = 0 ;
lavf/vf_vpp_qsv: add support for QSV transpose filter
Add transpose support for qsv_vpp with rotate and hflip:
- rotate: [0, 3] support clockwise rotation of 0, 90, 180, 270;
- hflip: [0, 1] support horizontal flip;
Configure with:
{"cclock_hflip","clock","cclock","clock_hflip","reversal","hflip","vflip"}
CMD:
ffmpeg -hwaccel qsv -c:v h264_qsv -i input.h264
-vf 'format=qsv,vpp_qsv=transpose=clock' -c:v h264_qsv output.h264
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -c:v h264_qsv -i input.h264
-vf 'hwupload=extra_hw_frames=64,format=qsv,vpp_qsv=transpose=cclock_hflip'
-f rawvideo -pix_fmt nv12 ./transpose.yuv
Signed-off-by: Linjie Fu <linjie.fu@intel.com>
Signed-off-by: Zhong Li <zhong.li@intel.com>
2019-07-10 17:57:46 +00:00
}
}
if ( vpp - > hflip ) {
2022-05-22 12:19:11 +00:00
if ( QSV_RUNTIME_VERSION_ATLEAST ( mfx_version , 1 , 19 ) ) {
2022-12-05 06:25:08 +00:00
INIT_MFX_EXTBUF ( mirroring_conf , MFX_EXTBUFF_VPP_MIRRORING ) ;
SET_MFX_PARAM_FIELD ( mirroring_conf , Type , vpp - > hflip ) ;
2022-05-22 12:19:11 +00:00
} else {
av_log ( ctx , AV_LOG_WARNING , " The QSV VPP hflip option is "
" not supported with this MSDK version. \n " ) ;
vpp - > hflip = 0 ;
}
lavf/vf_vpp_qsv: add support for QSV transpose filter
Add transpose support for qsv_vpp with rotate and hflip:
- rotate: [0, 3] support clockwise rotation of 0, 90, 180, 270;
- hflip: [0, 1] support horizontal flip;
Configure with:
{"cclock_hflip","clock","cclock","clock_hflip","reversal","hflip","vflip"}
CMD:
ffmpeg -hwaccel qsv -c:v h264_qsv -i input.h264
-vf 'format=qsv,vpp_qsv=transpose=clock' -c:v h264_qsv output.h264
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -c:v h264_qsv -i input.h264
-vf 'hwupload=extra_hw_frames=64,format=qsv,vpp_qsv=transpose=cclock_hflip'
-f rawvideo -pix_fmt nv12 ./transpose.yuv
Signed-off-by: Linjie Fu <linjie.fu@intel.com>
Signed-off-by: Zhong Li <zhong.li@intel.com>
2019-07-10 17:57:46 +00:00
}
2022-11-28 04:43:21 +00:00
if ( inlink - > w ! = outlink - > w | | inlink - > h ! = outlink - > h | | in_format ! = vpp - > out_format ) {
2022-01-07 07:01:31 +00:00
if ( QSV_RUNTIME_VERSION_ATLEAST ( mfx_version , 1 , 19 ) ) {
2022-12-05 06:25:08 +00:00
INIT_MFX_EXTBUF ( scale_conf , MFX_EXTBUFF_VPP_SCALING ) ;
SET_MFX_PARAM_FIELD ( scale_conf , ScalingMode , vpp - > scale_mode ) ;
2022-01-07 07:01:31 +00:00
} else
2022-11-28 04:43:21 +00:00
av_log ( ctx , AV_LOG_WARNING , " The QSV VPP Scale & format conversion "
" option is not supported with this MSDK version. \n " ) ;
2021-02-24 01:41:58 +00:00
}
2022-12-05 06:25:08 +00:00
# undef INIT_MFX_EXTBUF
# undef SET_MFX_PARAM_FIELD
2018-04-04 09:51:30 +00:00
if ( vpp - > use_frc | | vpp - > use_crop | | vpp - > deinterlace | | vpp - > denoise | |
lavf/vf_vpp_qsv: add support for QSV transpose filter
Add transpose support for qsv_vpp with rotate and hflip:
- rotate: [0, 3] support clockwise rotation of 0, 90, 180, 270;
- hflip: [0, 1] support horizontal flip;
Configure with:
{"cclock_hflip","clock","cclock","clock_hflip","reversal","hflip","vflip"}
CMD:
ffmpeg -hwaccel qsv -c:v h264_qsv -i input.h264
-vf 'format=qsv,vpp_qsv=transpose=clock' -c:v h264_qsv output.h264
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -c:v h264_qsv -i input.h264
-vf 'hwupload=extra_hw_frames=64,format=qsv,vpp_qsv=transpose=cclock_hflip'
-f rawvideo -pix_fmt nv12 ./transpose.yuv
Signed-off-by: Linjie Fu <linjie.fu@intel.com>
Signed-off-by: Zhong Li <zhong.li@intel.com>
2019-07-10 17:57:46 +00:00
vpp - > detail | | vpp - > procamp | | vpp - > rotate | | vpp - > hflip | |
2019-08-15 02:33:57 +00:00
inlink - > w ! = outlink - > w | | inlink - > h ! = outlink - > h | | in_format ! = vpp - > out_format )
2018-04-04 09:51:30 +00:00
return ff_qsvvpp_create ( ctx , & vpp - > qsv , & param ) ;
else {
av_log ( ctx , AV_LOG_VERBOSE , " qsv vpp pass through mode. \n " ) ;
if ( inlink - > hw_frames_ctx )
outlink - > hw_frames_ctx = av_buffer_ref ( inlink - > hw_frames_ctx ) ;
}
return 0 ;
2017-08-24 02:16:28 +00:00
}
2021-03-31 02:07:44 +00:00
static int activate ( AVFilterContext * ctx )
2017-08-24 02:16:28 +00:00
{
2021-03-31 02:07:44 +00:00
AVFilterLink * inlink = ctx - > inputs [ 0 ] ;
AVFilterLink * outlink = ctx - > outputs [ 0 ] ;
VPPContext * s = ctx - > priv ;
QSVVPPContext * qsv = s - > qsv ;
AVFrame * in = NULL ;
2021-09-15 05:15:18 +00:00
int ret , status = 0 ;
int64_t pts = AV_NOPTS_VALUE ;
2021-03-31 02:07:44 +00:00
FF_FILTER_FORWARD_STATUS_BACK ( outlink , inlink ) ;
if ( ! s - > eof ) {
ret = ff_inlink_consume_frame ( inlink , & in ) ;
if ( ret < 0 )
return ret ;
if ( ff_inlink_acknowledge_status ( inlink , & status , & pts ) ) {
if ( status = = AVERROR_EOF ) {
s - > eof = 1 ;
}
}
}
if ( qsv ) {
if ( in | | s - > eof ) {
qsv - > eof = s - > eof ;
ret = ff_qsvvpp_filter_frame ( qsv , inlink , in ) ;
av_frame_free ( & in ) ;
2022-05-12 01:18:21 +00:00
if ( ret = = AVERROR ( EAGAIN ) )
goto not_ready ;
else if ( ret < 0 )
return ret ;
2021-03-31 02:07:44 +00:00
2022-05-12 01:18:21 +00:00
if ( s - > eof )
goto eof ;
2021-03-31 02:07:44 +00:00
if ( qsv - > got_frame ) {
qsv - > got_frame = 0 ;
2022-05-12 01:18:21 +00:00
return 0 ;
2021-03-31 02:07:44 +00:00
}
}
2018-04-03 01:50:20 +00:00
} else {
2021-03-31 02:07:44 +00:00
if ( in ) {
if ( in - > pts ! = AV_NOPTS_VALUE )
in - > pts = av_rescale_q ( in - > pts , inlink - > time_base , outlink - > time_base ) ;
ret = ff_filter_frame ( outlink , in ) ;
2022-05-12 01:18:21 +00:00
if ( ret < 0 )
return ret ;
if ( s - > eof )
goto eof ;
return 0 ;
2021-03-31 02:07:44 +00:00
}
2018-04-04 09:51:30 +00:00
}
2017-08-24 02:16:28 +00:00
2022-05-12 01:18:21 +00:00
not_ready :
if ( s - > eof )
goto eof ;
FF_FILTER_FORWARD_WANTED ( outlink , inlink ) ;
2021-03-31 02:07:44 +00:00
return FFERROR_NOT_READY ;
2022-05-12 01:18:21 +00:00
eof :
ff_outlink_set_status ( outlink , status , pts ) ;
return 0 ;
2017-08-24 02:16:28 +00:00
}
static int query_formats ( AVFilterContext * ctx )
{
2017-11-20 09:14:34 +00:00
int ret ;
2017-08-24 02:16:28 +00:00
static const enum AVPixelFormat in_pix_fmts [ ] = {
AV_PIX_FMT_YUV420P ,
AV_PIX_FMT_NV12 ,
AV_PIX_FMT_YUYV422 ,
AV_PIX_FMT_RGB32 ,
2022-12-06 07:21:10 +00:00
AV_PIX_FMT_P010 ,
2017-08-24 02:16:28 +00:00
AV_PIX_FMT_QSV ,
AV_PIX_FMT_NONE
} ;
static const enum AVPixelFormat out_pix_fmts [ ] = {
AV_PIX_FMT_NV12 ,
2019-05-31 00:44:48 +00:00
AV_PIX_FMT_P010 ,
2017-08-24 02:16:28 +00:00
AV_PIX_FMT_QSV ,
AV_PIX_FMT_NONE
} ;
2020-08-07 03:54:34 +00:00
ret = ff_formats_ref ( ff_make_format_list ( in_pix_fmts ) ,
2020-08-24 10:16:34 +00:00
& ctx - > inputs [ 0 ] - > outcfg . formats ) ;
2017-11-20 09:14:34 +00:00
if ( ret < 0 )
return ret ;
2020-08-07 03:54:34 +00:00
return ff_formats_ref ( ff_make_format_list ( out_pix_fmts ) ,
2020-08-24 10:16:34 +00:00
& ctx - > outputs [ 0 ] - > incfg . formats ) ;
2017-08-24 02:16:28 +00:00
}
static av_cold void vpp_uninit ( AVFilterContext * ctx )
{
VPPContext * vpp = ctx - > priv ;
ff_qsvvpp_free ( & vpp - > qsv ) ;
}
static const AVClass vpp_class = {
. class_name = " vpp_qsv " ,
. item_name = av_default_item_name ,
. option = options ,
. version = LIBAVUTIL_VERSION_INT ,
} ;
static const AVFilterPad vpp_inputs [ ] = {
{
. name = " default " ,
. type = AVMEDIA_TYPE_VIDEO ,
. config_props = config_input ,
2022-12-05 06:32:13 +00:00
. get_buffer . video = ff_qsvvpp_get_video_buffer ,
2017-08-24 02:16:28 +00:00
} ,
} ;
static const AVFilterPad vpp_outputs [ ] = {
{
. name = " default " ,
. type = AVMEDIA_TYPE_VIDEO ,
. config_props = config_output ,
} ,
} ;
2021-04-19 16:33:56 +00:00
const AVFilter ff_vf_vpp_qsv = {
2017-08-24 02:16:28 +00:00
. name = " vpp_qsv " ,
. description = NULL_IF_CONFIG_SMALL ( " Quick Sync Video VPP. " ) ,
. priv_size = sizeof ( VPPContext ) ,
2019-05-31 00:44:47 +00:00
. init = vpp_init ,
2017-08-24 02:16:28 +00:00
. uninit = vpp_uninit ,
2021-08-12 11:05:31 +00:00
FILTER_INPUTS ( vpp_inputs ) ,
FILTER_OUTPUTS ( vpp_outputs ) ,
2021-09-27 10:07:35 +00:00
FILTER_QUERY_FUNC ( query_formats ) ,
2021-03-31 02:07:44 +00:00
. activate = activate ,
2017-08-24 02:16:28 +00:00
. priv_class = & vpp_class ,
. flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE ,
} ;