@ -467,6 +467,27 @@ namespace MediaBrowser.Controller.MediaEncoding
. Append ( ' ' ) ;
}
if ( state . IsVideoRequest
& & string . Equals ( encodingOptions . HardwareAccelerationType , "qsv" , StringComparison . OrdinalIgnoreCase ) )
{
var videoDecoder = GetHardwareAcceleratedVideoDecoder ( state , encodingOptions ) ;
var outputVideoCodec = GetVideoEncoder ( state , encodingOptions ) ;
if ( encodingOptions . EnableHardwareEncoding & & outputVideoCodec . Contains ( "qsv" , StringComparison . OrdinalIgnoreCase ) )
{
if ( ! string . IsNullOrEmpty ( videoDecoder ) & & videoDecoder . Contains ( "qsv" , StringComparison . OrdinalIgnoreCase ) )
{
arg . Append ( "-hwaccel qsv " ) ;
}
else
{
arg . Append ( "-init_hw_device qsv=hw -filter_hw_device hw " ) ;
}
}
arg . Append ( videoDecoder + " " ) ;
}
arg . Append ( "-i " )
. Append ( GetInputPathArgument ( state ) ) ;
@ -1562,6 +1583,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var videoSizeParam = string . Empty ;
// Setup subtitle scaling
if ( state . VideoStream ! = null & & state . VideoStream . Width . HasValue & & state . VideoStream . Height . HasValue )
{
videoSizeParam = string . Format (
@ -1570,7 +1592,11 @@ namespace MediaBrowser.Controller.MediaEncoding
state . VideoStream . Width . Value ,
state . VideoStream . Height . Value ) ;
videoSizeParam + = ":force_original_aspect_ratio=decrease" ;
//For QSV, feed it into hardware encoder now
if ( string . Equals ( outputVideoCodec , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) )
{
videoSizeParam + = ",hwupload=extra_hw_frames=64" ;
}
}
var mapPrefix = state . SubtitleStream . IsExternal ?
@ -1581,9 +1607,31 @@ namespace MediaBrowser.Controller.MediaEncoding
? 0
: state . SubtitleStream . Index ;
var videoDecoder = GetHardwareAcceleratedVideoDecoder ( state , options ) ;
// Setup default filtergraph utilizing FFMpeg overlay() and FFMpeg scale() (see the return of this function for index reference)
var retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay{3}\"" ;
if ( string . Equals ( outputVideoCodec , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) )
{
/ *
QSV in FFMpeg can now setup hardware overlay for transcodes .
For software decoding and hardware encoding option , frames must be hwuploaded into hardware
with fixed frame size .
* /
if ( ! string . IsNullOrEmpty ( videoDecoder ) & & videoDecoder . Contains ( "qsv" , StringComparison . OrdinalIgnoreCase ) )
{
retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay_qsv=x=(W-w)/2:y=(H-h)/2{3}\"" ;
}
else
{
retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]hwupload=extra_hw_frames=64[v];[v][sub]overlay_qsv=x=(W-w)/2:y=(H-h)/2{3}\"" ;
}
}
return string . Format (
CultureInfo . InvariantCulture ,
" -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay{3}\"" ,
retStr ,
mapPrefix ,
subtitleStreamIndex ,
state . VideoStream . Index ,
@ -1647,31 +1695,34 @@ namespace MediaBrowser.Controller.MediaEncoding
requestedMaxWidth ,
requestedMaxHeight ) ;
if ( string . Equals ( videoEncoder , "h264_vaapi" , StringComparison . OrdinalIgnoreCase )
if ( ( string . Equals ( videoEncoder , "h264_vaapi" , StringComparison . OrdinalIgnoreCase ) | | string . Equals ( videoEncoder , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) )
& & width . HasValue
& & height . HasValue )
{
// Work around vaapi's reduced scaling features
var scaler = "scale_vaapi" ;
// Given the input dimensions (inputWidth, inputHeight), determine the output dimensions
// (outputWidth, outputHeight). The user may request precise output dimensions or maximum
// output dimensions. Output dimensions are guaranteed to be even.
var outputWidth = width . Value ;
var outputHeight = height . Value ;
var vaapi_or_qsv = string . Equals ( videoEncoder , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) ? "qsv" : "vaapi" ;
if ( ! videoWidth . HasValue
| | outputWidth ! = videoWidth . Value
| | ! videoHeight . HasValue
| | outputHeight ! = videoHeight . Value )
{
// Force nv12 pixel format to enable 10-bit to 8-bit colour conversion.
filters . Add (
string . Format (
CultureInfo . InvariantCulture ,
" {0}=w={1}:h={2}",
scaler ,
" scale_ {0}=w={1}:h={2}:format=nv12 ",
vaapi_or_qsv ,
outputWidth ,
outputHeight ) ) ;
}
else
{
filters . Add ( string . Format ( CultureInfo . InvariantCulture , "scale_{0}=format=nv12" , vaapi_or_qsv ) ) ;
}
}
else if ( ( videoDecoder ? ? string . Empty ) . IndexOf ( "_cuvid" , StringComparison . OrdinalIgnoreCase ) ! = - 1
@ -1914,10 +1965,26 @@ namespace MediaBrowser.Controller.MediaEncoding
filters . Add ( "hwupload" ) ;
}
if ( state . DeInterlace ( "h264" , true )
& & string . Equals ( outputVideoCodec , "h264_vaapi" , StringComparison . OrdinalIgnoreCase ) )
var videoDecoder = GetHardwareAcceleratedVideoDecoder ( state , options ) ;
// If we are software decoding, and hardware encoding
if ( string . Equals ( outputVideoCodec , "h264_qsv" , StringComparison . OrdinalIgnoreCase )
& & ( string . IsNullOrEmpty ( videoDecoder ) | | ! videoDecoder . Contains ( "qsv" , StringComparison . OrdinalIgnoreCase ) ) )
{
filters . Add ( "format=nv12|qsv" ) ;
filters . Add ( "hwupload=extra_hw_frames=64" ) ;
}
if ( state . DeInterlace ( "h264" , true ) )
{
filters . Add ( string . Format ( CultureInfo . InvariantCulture , "deinterlace_vaapi" ) ) ;
if ( string . Equals ( outputVideoCodec , "h264_vaapi" , StringComparison . OrdinalIgnoreCase ) )
{
filters . Add ( string . Format ( CultureInfo . InvariantCulture , "deinterlace_vaapi" ) ) ;
}
else if ( string . Equals ( outputVideoCodec , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) )
{
filters . Add ( string . Format ( CultureInfo . InvariantCulture , "deinterlace_qsv" ) ) ;
}
}
if ( ( state . DeInterlace ( "h264" , true ) | | state . DeInterlace ( "h265" , true ) | | state . DeInterlace ( "hevc" , true ) )
@ -1940,8 +2007,6 @@ namespace MediaBrowser.Controller.MediaEncoding
var inputHeight = videoStream ? . Height ;
var threeDFormat = state . MediaSource . Video3DFormat ;
var videoDecoder = GetHardwareAcceleratedVideoDecoder ( state , options ) ;
filters . AddRange ( GetScalingFilters ( inputWidth , inputHeight , threeDFormat , videoDecoder , outputVideoCodec , request . Width , request . Height , request . MaxWidth , request . MaxHeight ) ) ;
var output = string . Empty ;
@ -2134,6 +2199,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
var videoDecoder = GetHardwareAcceleratedVideoDecoder ( state , encodingOptions ) ;
if ( ! string . IsNullOrEmpty ( videoDecoder ) )
{
inputModifier + = " " + videoDecoder ;