@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization ;
using System.IO ;
using System.Linq ;
using System.Runtime.InteropServices ;
using System.Text ;
using System.Threading ;
using Jellyfin.Data.Enums ;
@ -449,41 +450,59 @@ namespace MediaBrowser.Controller.MediaEncoding
var arg = new StringBuilder ( ) ;
var videoDecoder = GetHardwareAcceleratedVideoDecoder ( state , encodingOptions ) ? ? string . Empty ;
var outputVideoCodec = GetVideoEncoder ( state , encodingOptions ) ? ? string . Empty ;
bool isVaapiDecoder = videoDecoder . IndexOf ( "vaapi" , StringComparison . OrdinalIgnoreCase ) ! = - 1 ;
bool isVaapiEncoder = outputVideoCodec . IndexOf ( "vaapi" , StringComparison . OrdinalIgnoreCase ) ! = - 1 ;
bool isQsvDecoder = videoDecoder . IndexOf ( "qsv" , StringComparison . OrdinalIgnoreCase ) ! = - 1 ;
bool isQsvEncoder = outputVideoCodec . IndexOf ( "qsv" , StringComparison . OrdinalIgnoreCase ) ! = - 1 ;
var isVaapiDecoder = videoDecoder . IndexOf ( "vaapi" , StringComparison . OrdinalIgnoreCase ) ! = - 1 ;
var isVaapiEncoder = outputVideoCodec . IndexOf ( "vaapi" , StringComparison . OrdinalIgnoreCase ) ! = - 1 ;
var isQsvDecoder = videoDecoder . IndexOf ( "qsv" , StringComparison . OrdinalIgnoreCase ) ! = - 1 ;
var isQsvEncoder = outputVideoCodec . IndexOf ( "qsv" , StringComparison . OrdinalIgnoreCase ) ! = - 1 ;
var isWindows = RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ;
var isLinux = RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) ;
if ( state . IsVideoRequest
& & string . Equals ( encodingOptions . HardwareAccelerationType , "vaapi" , StringComparison . OrdinalIgnoreCase ) )
if ( ! IsCopyCodec ( outputVideoCodec ) )
{
if ( isVaapiDecoder )
if ( state . IsVideoRequest
& & IsVaapiSupported ( state )
& & string . Equals ( encodingOptions . HardwareAccelerationType , "vaapi" , StringComparison . OrdinalIgnoreCase ) )
{
arg . Append ( "-hwaccel_output_format vaapi " )
. Append ( "-vaapi_device " )
. Append ( encodingOptions . VaapiDevice )
. Append ( " " ) ;
}
else if ( ! isVaapiDecoder & & isVaapiEncoder )
{
arg . Append ( "-vaapi_device " )
. Append ( encodingOptions . VaapiDevice )
. Append ( " " ) ;
if ( isVaapiDecoder )
{
arg . Append ( "-hwaccel_output_format vaapi " )
. Append ( "-vaapi_device " )
. Append ( encodingOptions . VaapiDevice )
. Append ( " " ) ;
}
else if ( ! isVaapiDecoder & & isVaapiEncoder )
{
arg . Append ( "-vaapi_device " )
. Append ( encodingOptions . VaapiDevice )
. Append ( " " ) ;
}
}
}
if ( state . IsVideoRequest
& & string . Equals ( encodingOptions . HardwareAccelerationType , "qsv" , StringComparison . OrdinalIgnoreCase ) )
{
var hasTextSubs = state . SubtitleStream ! = null & & state . SubtitleStream . IsTextSubtitleStream & & state . SubtitleDeliveryMethod = = SubtitleDeliveryMethod . Encode ;
if ( ! hasTextSubs )
if ( state . IsVideoRequest
& & string . Equals ( encodingOptions . HardwareAccelerationType , "qsv" , StringComparison . OrdinalIgnoreCase ) )
{
if ( isQsvEncoder )
var hasGraphicalSubs = state . SubtitleStream ! = null & & ! state . SubtitleStream . IsTextSubtitleStream & & state . SubtitleDeliveryMethod = = SubtitleDeliveryMethod . Encode ;
if ( isQsvEncoder )
{
if ( isQsvDecoder )
{
arg . Append ( "-hwaccel qsv -init_hw_device qsv=hw " ) ;
if ( isLinux )
{
if ( hasGraphicalSubs )
{
arg . Append ( "-init_hw_device qsv=hw -filter_hw_device hw " ) ;
}
else
{
arg . Append ( "-hwaccel qsv -init_hw_device qsv=hw " ) ;
}
}
if ( isWindows )
{
arg . Append ( "-hwaccel qsv -init_hw_device qsv=hw " ) ;
}
}
// While using SW decoder
else
@ -806,6 +825,34 @@ namespace MediaBrowser.Controller.MediaEncoding
break ;
}
}
else if ( string . Equals ( videoEncoder , "h264_amf" , StringComparison . OrdinalIgnoreCase )
| | string . Equals ( videoEncoder , "hevc_amf" , StringComparison . OrdinalIgnoreCase ) )
{
switch ( encodingOptions . EncoderPreset )
{
case "veryslow" :
case "slow" :
case "slower" :
param + = "-quality quality" ;
break ;
case "medium" :
param + = "-quality balanced" ;
break ;
case "fast" :
case "faster" :
case "veryfast" :
case "superfast" :
case "ultrafast" :
param + = "-quality speed" ;
break ;
default :
param + = "-quality speed" ;
break ;
}
}
else if ( string . Equals ( videoEncoder , "libvpx" , StringComparison . OrdinalIgnoreCase ) ) // webm
{
// Values 0-3, 0 being highest quality but slower
@ -1555,28 +1602,28 @@ namespace MediaBrowser.Controller.MediaEncoding
var index = outputSizeParam . IndexOf ( "hwdownload" , StringComparison . OrdinalIgnoreCase ) ;
if ( index ! = - 1 )
{
outputSizeParam = "," + outputSizeParam . Substring ( index ) ;
outputSizeParam = outputSizeParam . Substring ( index ) ;
}
else
{
index = outputSizeParam . IndexOf ( "format" , StringComparison . OrdinalIgnoreCase ) ;
if ( index ! = - 1 )
{
outputSizeParam = "," + outputSizeParam . Substring ( index ) ;
outputSizeParam = outputSizeParam . Substring ( index ) ;
}
else
{
index = outputSizeParam . IndexOf ( "yadif" , StringComparison . OrdinalIgnoreCase ) ;
if ( index ! = - 1 )
{
outputSizeParam = "," + outputSizeParam . Substring ( index ) ;
outputSizeParam = outputSizeParam . Substring ( index ) ;
}
else
{
index = outputSizeParam . IndexOf ( "scale" , StringComparison . OrdinalIgnoreCase ) ;
if ( index ! = - 1 )
{
outputSizeParam = "," + outputSizeParam . Substring ( index ) ;
outputSizeParam = outputSizeParam . Substring ( index ) ;
}
}
}
@ -1585,43 +1632,30 @@ namespace MediaBrowser.Controller.MediaEncoding
var videoSizeParam = string . Empty ;
var videoDecoder = GetHardwareAcceleratedVideoDecoder ( state , options ) ? ? string . Empty ;
var isLinux = RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) ;
// Setup subtitle scaling
if ( state . VideoStream ! = null & & state . VideoStream . Width . HasValue & & state . VideoStream . Height . HasValue )
{
videoSizeParam = string . Format (
CultureInfo . InvariantCulture ,
"scale={0}:{1}" ,
state . VideoStream . Width . Value ,
state . VideoStream . Height . Value ) ;
// Adjust the size of graphical subtitles to fit the video stream.
var videoStream = state . VideoStream ;
var inputWidth = videoStream ? . Width ;
var inputHeight = videoStream ? . Height ;
var ( width , height ) = GetFixedOutputSize ( inputWidth , inputHeight , request . Width , request . Height , request . MaxWidth , request . MaxHeight ) ;
// For QSV, feed it into hardware encoder now
if ( string . Equals ( outputVideoCodec , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) )
if ( width . HasValue & & height . HasValue )
{
videoSizeParam + = ",hwupload=extra_hw_frames=64" ;
}
// For VAAPI and CUVID decoder
// these encoders cannot automatically adjust the size of graphical subtitles to fit the output video,
// thus needs to be manually adjusted.
if ( videoDecoder . IndexOf ( "cuvid" , StringComparison . OrdinalIgnoreCase ) ! = - 1
| | ( IsVaapiSupported ( state ) & & string . Equals ( options . HardwareAccelerationType , "vaapi" , StringComparison . OrdinalIgnoreCase )
& & ( videoDecoder . IndexOf ( "vaapi" , StringComparison . OrdinalIgnoreCase ) ! = - 1
| | outputVideoCodec . IndexOf ( "vaapi" , StringComparison . OrdinalIgnoreCase ) ! = - 1 ) ) )
{
var videoStream = state . VideoStream ;
var inputWidth = videoStream ? . Width ;
var inputHeight = videoStream ? . Height ;
var ( width , height ) = GetFixedOutputSize ( inputWidth , inputHeight , request . Width , request . Height , request . MaxWidth , request . MaxHeight ) ;
if ( width . HasValue & & height . HasValue )
{
videoSizeParam = string . Format (
videoSizeParam = string . Format (
CultureInfo . InvariantCulture ,
"scale={0} : {1}",
"scale={0}x{1}" ,
width . Value ,
height . Value ) ;
}
}
// For QSV, feed it into hardware encoder now
if ( isLinux & & string . Equals ( outputVideoCodec , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) )
{
videoSizeParam + = ",hwupload=extra_hw_frames=64" ;
}
}
@ -1634,7 +1668,10 @@ namespace MediaBrowser.Controller.MediaEncoding
: state . SubtitleStream . Index ;
// 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}\"" ;
// Always put the scaler before the overlay for better performance
var retStr = ! string . IsNullOrEmpty ( outputSizeParam ) ?
" -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\"" :
" -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay\"" ;
// When the input may or may not be hardware VAAPI decodable
if ( string . Equals ( outputVideoCodec , "h264_vaapi" , StringComparison . OrdinalIgnoreCase ) )
@ -1644,7 +1681,6 @@ namespace MediaBrowser.Controller.MediaEncoding
[sub] : SW scaling subtitle to FixedOutputSize
[base] [ sub ] : SW overlay
* /
outputSizeParam = outputSizeParam . TrimStart ( ',' ) ;
retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3},hwdownload[base];[base][sub]overlay,format=nv12,hwupload\"" ;
}
@ -1657,7 +1693,6 @@ namespace MediaBrowser.Controller.MediaEncoding
[sub] : SW scaling subtitle to FixedOutputSize
[base] [ sub ] : SW overlay
* /
outputSizeParam = outputSizeParam . TrimStart ( ',' ) ;
retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\"" ;
}
else if ( string . Equals ( outputVideoCodec , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) )
@ -1666,14 +1701,13 @@ namespace MediaBrowser.Controller.MediaEncoding
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 .
Currently only supports linux .
* /
if ( videoDecoder. IndexOf ( "qsv" , StringComparison . OrdinalIgnoreCase ) ! = - 1 )
if ( isLinux )
{
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}\"" ;
retStr = ! string . IsNullOrEmpty ( outputSizeParam ) ?
" -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay_qsv\"" :
" -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay_qsv\"" ;
}
}
@ -1745,10 +1779,8 @@ namespace MediaBrowser.Controller.MediaEncoding
requestedMaxWidth ,
requestedMaxHeight ) ;
var hasTextSubs = state . SubtitleStream ! = null & & state . SubtitleStream . IsTextSubtitleStream & & state . SubtitleDeliveryMethod = = SubtitleDeliveryMethod . Encode ;
if ( ( string . Equals ( videoEncoder , "h264_vaapi" , StringComparison . OrdinalIgnoreCase )
| | ( string . Equals ( videoEncoder , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) & & ! hasTextSubs ) )
| | string . Equals ( videoEncoder , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) )
& & width . HasValue
& & height . HasValue )
{
@ -1769,15 +1801,20 @@ namespace MediaBrowser.Controller.MediaEncoding
filters . Add (
string . Format (
CultureInfo . InvariantCulture ,
"{0}=w={1}:h={2}:format=nv12 ",
"{0}=w={1}:h={2}:format=nv12 {3} ",
qsv_or_vaapi ? "vpp_qsv" : "scale_vaapi" ,
outputWidth ,
outputHeight ) ) ;
outputHeight ,
( qsv_or_vaapi & & state . DeInterlace ( "h264" , true ) ) ? ":deinterlace=1" : string . Empty ) ) ;
}
else
{
// set w=0:h=0 for vpp_qsv to keep the original dimensions, otherwise it will fail.
filters . Add ( string . Format ( CultureInfo . InvariantCulture , "{0}format=nv12" , qsv_or_vaapi ? "vpp_qsv=w=0:h=0:" : "scale_vaapi=" ) ) ;
filters . Add (
string . Format (
CultureInfo . InvariantCulture ,
"{0}=format=nv12{1}" ,
qsv_or_vaapi ? "vpp_qsv" : "scale_vaapi" ,
( qsv_or_vaapi & & state . DeInterlace ( "h264" , true ) ) ? ":deinterlace=1" : string . Empty ) ) ;
}
}
else if ( ( videoDecoder ? ? string . Empty ) . IndexOf ( "cuvid" , StringComparison . OrdinalIgnoreCase ) ! = - 1
@ -1998,8 +2035,6 @@ namespace MediaBrowser.Controller.MediaEncoding
var inputHeight = videoStream ? . Height ;
var threeDFormat = state . MediaSource . Video3DFormat ;
var hasTextSubs = state . SubtitleStream ! = null & & state . SubtitleStream . IsTextSubtitleStream & & state . SubtitleDeliveryMethod = = SubtitleDeliveryMethod . Encode ;
// When the input may or may not be hardware VAAPI decodable
if ( string . Equals ( outputVideoCodec , "h264_vaapi" , StringComparison . OrdinalIgnoreCase ) )
{
@ -2010,20 +2045,16 @@ namespace MediaBrowser.Controller.MediaEncoding
// When the input may or may not be hardware QSV decodable
else if ( string . Equals ( outputVideoCodec , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) )
{
if ( ! hasTextSubs )
{
filters . Add ( "format=nv12|qsv" ) ;
filters . Add ( "hwupload=extra_hw_frames=64" ) ;
}
filters . Add ( "format=nv12|qsv" ) ;
filters . Add ( "hwupload=extra_hw_frames=64" ) ;
}
// If we're hardware VAAPI decoding and software encoding, download frames from the decoder first
else if ( videoDecoder. IndexOf ( "vaapi" , StringComparison . OrdinalIgnoreCase ) ! = - 1
else if ( IsVaapiSupported( state ) & & videoDecoder. IndexOf ( "vaapi" , StringComparison . OrdinalIgnoreCase ) ! = - 1
& & string . Equals ( outputVideoCodec , "libx264" , StringComparison . OrdinalIgnoreCase ) )
{
var codec = videoStream . Codec . ToLowerInvariant ( ) ;
var isColorDepth10 = ! string . IsNullOrEmpty ( videoStream . Profile ) & & ( videoStream . Profile . Contains ( "Main 10" , StringComparison . OrdinalIgnoreCase )
| | videoStream . Profile . Contains ( "High 10" , StringComparison . OrdinalIgnoreCase ) ) ;
var isColorDepth10 = IsColorDepth10 ( state ) ;
// Assert 10-bit hardware VAAPI decodable
if ( isColorDepth10 & & ( string . Equals ( codec , "hevc" , StringComparison . OrdinalIgnoreCase )
@ -2054,31 +2085,32 @@ namespace MediaBrowser.Controller.MediaEncoding
{
filters . Add ( string . Format ( CultureInfo . InvariantCulture , "deinterlace_vaapi" ) ) ;
}
else if ( string . Equals ( outputVideoCodec , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) )
{
if ( ! hasTextSubs )
{
filters . Add ( string . Format ( CultureInfo . InvariantCulture , "deinterlace_qsv" ) ) ;
}
}
}
// Add software deinterlace filter before scaling filter
if ( ( ( state . DeInterlace ( "h264" , true ) | | state . DeInterlace ( "h265" , true ) | | state . DeInterlace ( "hevc" , true ) )
& & ! string . Equals ( outputVideoCodec , "h264_vaapi" , StringComparison . OrdinalIgnoreCase )
& & ! string . Equals ( outputVideoCodec , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) )
| | ( hasTextSubs & & state . DeInterlace ( "h264" , true ) & & string . Equals ( outputVideoCodec , "h264_qsv" , StringComparison . OrdinalIgnoreCase ) ) )
if ( state . DeInterlace ( "h264" , true ) | | state . DeInterlace ( "h265" , true ) | | state . DeInterlace ( "hevc" , true ) )
{
var deintParam = string . Empty ;
var inputFramerate = videoStream ? . RealFrameRate ;
// If it is already 60fps then it will create an output framerate that is much too high for roku and others to handle
if ( string . Equals ( options . DeinterlaceMethod , "yadif_bob" , StringComparison . OrdinalIgnoreCase ) & & ( inputFramerate ? ? 60 ) < = 30 )
{
filters. Add ( "yadif=1:-1:0" ) ;
deintParam = "yadif=1:-1:0" ;
}
else
{
filters . Add ( "yadif=0:-1:0" ) ;
deintParam = "yadif=0:-1:0" ;
}
if ( ! string . IsNullOrEmpty ( deintParam ) )
{
if ( ! string . Equals ( outputVideoCodec , "h264_vaapi" , StringComparison . OrdinalIgnoreCase )
& & ! string . Equals ( outputVideoCodec , "h264_qsv" , StringComparison . OrdinalIgnoreCase )
& & videoDecoder . IndexOf ( "h264_cuvid" , StringComparison . OrdinalIgnoreCase ) = = - 1 )
{
filters . Add ( deintParam ) ;
}
}
}
@ -2290,7 +2322,8 @@ namespace MediaBrowser.Controller.MediaEncoding
{
inputModifier + = " " + videoDecoder ;
if ( ( videoDecoder ? ? string . Empty ) . IndexOf ( "cuvid" , StringComparison . OrdinalIgnoreCase ) ! = - 1 )
if ( ! IsCopyCodec ( state . OutputVideoCodec )
& & ( videoDecoder ? ? string . Empty ) . IndexOf ( "cuvid" , StringComparison . OrdinalIgnoreCase ) ! = - 1 )
{
var videoStream = state . VideoStream ;
var inputWidth = videoStream ? . Width ;
@ -2303,11 +2336,19 @@ namespace MediaBrowser.Controller.MediaEncoding
& & width . HasValue
& & height . HasValue )
{
inputModifier + = string . Format (
CultureInfo . InvariantCulture ,
" -resize {0}x{1}" ,
width . Value ,
height . Value ) ;
if ( width . HasValue & & height . HasValue )
{
inputModifier + = string . Format (
CultureInfo . InvariantCulture ,
" -resize {0}x{1}" ,
width . Value ,
height . Value ) ;
}
if ( state . DeInterlace ( "h264" , true ) )
{
inputModifier + = " -deint 1" ;
}
}
}
}
@ -2553,8 +2594,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if ( ! string . IsNullOrEmpty ( videoStream . Codec ) & & ! string . IsNullOrEmpty ( encodingOptions . HardwareAccelerationType ) )
{
var isColorDepth10 = ! string . IsNullOrEmpty ( videoStream . Profile )
& & ( videoStream . Profile . Contains ( "Main 10" , StringComparison . OrdinalIgnoreCase ) | | videoStream . Profile . Contains ( "High 10" , StringComparison . OrdinalIgnoreCase ) ) ;
var isColorDepth10 = IsColorDepth10 ( state ) ;
// Only hevc and vp9 formats have 10-bit hardware decoder support now.
if ( isColorDepth10 & & ! ( string . Equals ( videoStream . Codec , "hevc" , StringComparison . OrdinalIgnoreCase )
@ -2631,13 +2671,6 @@ namespace MediaBrowser.Controller.MediaEncoding
case "h264" :
if ( _mediaEncoder . SupportsDecoder ( "h264_cuvid" ) & & encodingOptions . HardwareDecodingCodecs . Contains ( "h264" , StringComparer . OrdinalIgnoreCase ) )
{
// cuvid decoder does not support 10-bit input.
if ( ( videoStream . BitDepth ? ? 8 ) > 8 )
{
encodingOptions . HardwareDecodingCodecs = Array . Empty < string > ( ) ;
return null ;
}
return "-c:v h264_cuvid" ;
}
@ -2904,21 +2937,24 @@ namespace MediaBrowser.Controller.MediaEncoding
/// </summary>
public string GetHwaccelType ( EncodingJobInfo state , EncodingOptions options , string videoCodec )
{
var isWindows = Environment . OSVersion . Platform = = PlatformID . Win32NT ;
var isWindows = RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ;
var isLinux = RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) ;
var isWindows8orLater = Environment . OSVersion . Version . Major > 6 | | ( Environment . OSVersion . Version . Major = = 6 & & Environment . OSVersion . Version . Minor > 1 ) ;
var isDxvaSupported = _mediaEncoder . SupportsHwaccel ( "dxva2" ) | | _mediaEncoder . SupportsHwaccel ( "d3d11va" ) ;
if ( ( isDxvaSupported | | IsVaapiSupported ( state ) ) & & options . HardwareDecodingCodecs . Contains ( videoCodec , StringComparer . OrdinalIgnoreCase ) )
{
if ( ! isWindows )
if ( isLinux )
{
return "-hwaccel vaapi" ;
}
else if ( isWindows8orLater )
if ( isWindows & & isWindows8orLater )
{
return "-hwaccel d3d11va" ;
}
else
if ( isWindows & & ! isWindows8orLater )
{
return "-hwaccel dxva2" ;
}
@ -3187,5 +3223,42 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return string . Equals ( codec , "copy" , StringComparison . OrdinalIgnoreCase ) ;
}
public static bool IsColorDepth10 ( EncodingJobInfo state )
{
var result = false ;
var videoStream = state . VideoStream ;
if ( videoStream ! = null )
{
if ( ! string . IsNullOrEmpty ( videoStream . PixelFormat ) )
{
result = videoStream . PixelFormat . Contains ( "p10" , StringComparison . OrdinalIgnoreCase ) ;
if ( result )
{
return true ;
}
}
if ( ! string . IsNullOrEmpty ( videoStream . Profile ) )
{
result = videoStream . Profile . Contains ( "Main 10" , StringComparison . OrdinalIgnoreCase )
| | videoStream . Profile . Contains ( "High 10" , StringComparison . OrdinalIgnoreCase )
| | videoStream . Profile . Contains ( "Profile 2" , StringComparison . OrdinalIgnoreCase ) ;
if ( result )
{
return true ;
}
}
result = ( videoStream . BitDepth ? ? 8 ) = = 10 ;
if ( result )
{
return true ;
}
}
return result ;
}
}
}