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
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
{ " w " , " Output video width " , OFFSET ( ow ) , AV_OPT_TYPE_STRING , { . str = " cw " } , 0 , 255 , . flags = FLAGS } ,
{ " width " , " Output video width " , OFFSET ( ow ) , AV_OPT_TYPE_STRING , { . str = " cw " } , 0 , 255 , . flags = FLAGS } ,
{ " h " , " Output video height " , OFFSET ( oh ) , AV_OPT_TYPE_STRING , { . str = " w*ch/cw " } , 0 , 255 , . flags = FLAGS } ,
{ " height " , " Output video height " , 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 } ,
2021-02-24 01:41:58 +00:00
{ " scale_mode " , " scale 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 " } ,
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 " ,
NULL
} ;
enum var_name {
VAR_iW , VAR_IN_W ,
VAR_iH , VAR_IN_H ,
VAR_oW , VAR_OUT_W , VAR_W ,
VAR_oH , VAR_OUT_H , VAR_H ,
CW ,
CH ,
CX ,
CY ,
VAR_VARS_NB
} ;
static int eval_expr ( AVFilterContext * ctx )
{
# define PASS_EXPR(e, 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 ; \
} \
}
# define CALC_EXPR(e, v, i) {\
i = v = av_expr_eval ( e , var_values , NULL ) ; \
}
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 ) ;
var_values [ VAR_iW ] =
var_values [ VAR_IN_W ] = ctx - > inputs [ 0 ] - > w ;
var_values [ VAR_iH ] =
var_values [ VAR_IN_H ] = ctx - > inputs [ 0 ] - > h ;
/* crop params */
CALC_EXPR ( cw_expr , var_values [ CW ] , vpp - > crop_w ) ;
CALC_EXPR ( ch_expr , var_values [ CH ] , vpp - > crop_h ) ;
/* calc again in case cw is relative to ch */
CALC_EXPR ( cw_expr , var_values [ CW ] , vpp - > crop_w ) ;
CALC_EXPR ( w_expr ,
var_values [ VAR_OUT_W ] = var_values [ VAR_oW ] = var_values [ VAR_W ] ,
vpp - > out_width ) ;
CALC_EXPR ( h_expr ,
var_values [ VAR_OUT_H ] = var_values [ VAR_oH ] = var_values [ VAR_H ] ,
vpp - > out_height ) ;
/* calc again in case ow is relative to oh */
CALC_EXPR ( w_expr ,
var_values [ VAR_OUT_W ] = var_values [ VAR_oW ] = var_values [ VAR_W ] ,
vpp - > out_width ) ;
CALC_EXPR ( cx_expr , var_values [ CX ] , vpp - > crop_x ) ;
CALC_EXPR ( cy_expr , var_values [ CY ] , vpp - > crop_y ) ;
/* calc again in case cx is relative to cy */
CALC_EXPR ( cx_expr , var_values [ CX ] , vpp - > crop_x ) ;
if ( ( vpp - > crop_w ! = var_values [ VAR_iW ] ) | | ( vpp - > crop_h ! = var_values [ VAR_iH ] ) )
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 ;
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 ;
}
if ( vpp - > out_height = = 0 | | vpp - > out_width = = 0 ) {
vpp - > out_width = inlink - > w ;
vpp - > out_height = inlink - > h ;
}
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 ;
}
if ( vpp - > deinterlace ) {
memset ( & vpp - > deinterlace_conf , 0 , sizeof ( mfxExtVPPDeinterlacing ) ) ;
vpp - > deinterlace_conf . Header . BufferId = MFX_EXTBUFF_VPP_DEINTERLACING ;
vpp - > deinterlace_conf . Header . BufferSz = sizeof ( mfxExtVPPDeinterlacing ) ;
vpp - > deinterlace_conf . Mode = vpp - > deinterlace = = 1 ?
MFX_DEINTERLACING_BOB : MFX_DEINTERLACING_ADVANCED ;
param . ext_buf [ param . num_ext_buf + + ] = ( mfxExtBuffer * ) & vpp - > deinterlace_conf ;
}
if ( vpp - > use_frc ) {
memset ( & vpp - > frc_conf , 0 , sizeof ( mfxExtVPPFrameRateConversion ) ) ;
vpp - > frc_conf . Header . BufferId = MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION ;
vpp - > frc_conf . Header . BufferSz = sizeof ( mfxExtVPPFrameRateConversion ) ;
vpp - > frc_conf . Algorithm = MFX_FRCALGM_DISTRIBUTED_TIMESTAMP ;
param . ext_buf [ param . num_ext_buf + + ] = ( mfxExtBuffer * ) & vpp - > frc_conf ;
}
if ( vpp - > denoise ) {
memset ( & vpp - > denoise_conf , 0 , sizeof ( mfxExtVPPDenoise ) ) ;
vpp - > denoise_conf . Header . BufferId = MFX_EXTBUFF_VPP_DENOISE ;
vpp - > denoise_conf . Header . BufferSz = sizeof ( mfxExtVPPDenoise ) ;
vpp - > denoise_conf . DenoiseFactor = vpp - > denoise ;
param . ext_buf [ param . num_ext_buf + + ] = ( mfxExtBuffer * ) & vpp - > denoise_conf ;
}
if ( vpp - > detail ) {
memset ( & vpp - > detail_conf , 0 , sizeof ( mfxExtVPPDetail ) ) ;
vpp - > detail_conf . Header . BufferId = MFX_EXTBUFF_VPP_DETAIL ;
vpp - > detail_conf . Header . BufferSz = sizeof ( mfxExtVPPDetail ) ;
vpp - > detail_conf . DetailFactor = vpp - > detail ;
param . ext_buf [ param . num_ext_buf + + ] = ( mfxExtBuffer * ) & vpp - > detail_conf ;
}
if ( vpp - > procamp ) {
memset ( & vpp - > procamp_conf , 0 , sizeof ( mfxExtVPPProcAmp ) ) ;
vpp - > procamp_conf . Header . BufferId = MFX_EXTBUFF_VPP_PROCAMP ;
vpp - > procamp_conf . Header . BufferSz = sizeof ( mfxExtVPPProcAmp ) ;
vpp - > procamp_conf . Hue = vpp - > hue ;
vpp - > procamp_conf . Saturation = vpp - > saturation ;
vpp - > procamp_conf . Contrast = vpp - > contrast ;
vpp - > procamp_conf . Brightness = vpp - > brightness ;
param . ext_buf [ param . num_ext_buf + + ] = ( mfxExtBuffer * ) & vpp - > 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
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 ) ) {
memset ( & vpp - > rotation_conf , 0 , sizeof ( mfxExtVPPRotation ) ) ;
vpp - > rotation_conf . Header . BufferId = MFX_EXTBUFF_VPP_ROTATION ;
vpp - > rotation_conf . Header . BufferSz = sizeof ( mfxExtVPPRotation ) ;
vpp - > rotation_conf . Angle = vpp - > rotate ;
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 " ) ;
}
param . ext_buf [ param . num_ext_buf + + ] = ( mfxExtBuffer * ) & vpp - > rotation_conf ;
} 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 ) ) {
memset ( & vpp - > mirroring_conf , 0 , sizeof ( mfxExtVPPMirroring ) ) ;
vpp - > mirroring_conf . Header . BufferId = MFX_EXTBUFF_VPP_MIRRORING ;
vpp - > mirroring_conf . Header . BufferSz = sizeof ( mfxExtVPPMirroring ) ;
vpp - > mirroring_conf . Type = vpp - > hflip ;
param . ext_buf [ param . num_ext_buf + + ] = ( mfxExtBuffer * ) & vpp - > mirroring_conf ;
} 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-01-07 07:01:31 +00:00
if ( inlink - > w ! = outlink - > w | | inlink - > h ! = outlink - > h ) {
if ( QSV_RUNTIME_VERSION_ATLEAST ( mfx_version , 1 , 19 ) ) {
memset ( & vpp - > scale_conf , 0 , sizeof ( mfxExtVPPScaling ) ) ;
vpp - > scale_conf . Header . BufferId = MFX_EXTBUFF_VPP_SCALING ;
vpp - > scale_conf . Header . BufferSz = sizeof ( mfxExtVPPScaling ) ;
vpp - > scale_conf . ScalingMode = vpp - > scale_mode ;
param . ext_buf [ param . num_ext_buf + + ] = ( mfxExtBuffer * ) & vpp - > scale_conf ;
} else
av_log ( ctx , AV_LOG_WARNING , " The QSV VPP Scale option is "
" not supported with this MSDK version. \n " ) ;
2021-02-24 01:41:58 +00:00
}
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 ,
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 ,
} ,
} ;
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 ,
} ;