@ -93,19 +93,10 @@ namespace MediaBrowser.Model.Dlna
return GetOptimalStream ( streams , options . GetMaxBitrate ( false ) ? ? 0 ) ;
}
private StreamInfo GetOptimalStream ( List < StreamInfo > streams , long maxBitrate )
{
var sorted = SortMediaSources ( streams , maxBitrate ) ;
foreach ( StreamInfo stream in sorted )
{
return stream ;
}
private static StreamInfo GetOptimalStream ( List < StreamInfo > streams , long maxBitrate )
= > SortMediaSources ( streams , maxBitrate ) . FirstOrDefault ( ) ;
return null ;
}
private StreamInfo [ ] SortMediaSources ( List < StreamInfo > streams , long maxBitrate )
private static IOrderedEnumerable < StreamInfo > SortMediaSources ( List < StreamInfo > streams , long maxBitrate )
{
return streams . OrderBy ( i = >
{
@ -151,25 +142,17 @@ namespace MediaBrowser.Model.Dlna
return 0 ;
} ) . ThenBy ( streams . IndexOf ) .ToArray ( ) ;
} ) . ThenBy ( streams . IndexOf ) ;
}
private TranscodeReason ? GetTranscodeReasonForFailedCondition ( ProfileCondition condition )
private static TranscodeReason ? GetTranscodeReasonForFailedCondition ( ProfileCondition condition )
{
switch ( condition . Property )
{
case ProfileConditionValue . AudioBitrate :
if ( condition . Condition = = ProfileConditionType . LessThanEqual )
{
return TranscodeReason . AudioBitrateNotSupported ;
}
return TranscodeReason . AudioBitrateNotSupported ;
case ProfileConditionValue . AudioChannels :
if ( condition . Condition = = ProfileConditionType . LessThanEqual )
{
return TranscodeReason . AudioChannelsNotSupported ;
}
return TranscodeReason . AudioChannelsNotSupported ;
case ProfileConditionValue . AudioProfile :
@ -246,7 +229,7 @@ namespace MediaBrowser.Model.Dlna
}
}
public static string NormalizeMediaSourceFormatIntoSingleContainer ( string inputContainer , string unused1 , DeviceProfile profile , DlnaProfileType type )
public static string NormalizeMediaSourceFormatIntoSingleContainer ( string inputContainer , string _ , DeviceProfile profile , DlnaProfileType type )
{
if ( string . IsNullOrEmpty ( inputContainer ) )
{
@ -266,12 +249,10 @@ namespace MediaBrowser.Model.Dlna
{
foreach ( var directPlayProfile in profile . DirectPlayProfiles )
{
if ( directPlayProfile . Type = = type )
if ( directPlayProfile . Type = = type
& & directPlayProfile . SupportsContainer ( format ) )
{
if ( directPlayProfile . SupportsContainer ( format ) )
{
return format ;
}
return format ;
}
}
}
@ -282,9 +263,7 @@ namespace MediaBrowser.Model.Dlna
private StreamInfo BuildAudioItem ( MediaSourceInfo item , AudioOptions options )
{
var transcodeReasons = new List < TranscodeReason > ( ) ;
var playlistItem = new StreamInfo
StreamInfo playlistItem = new StreamInfo
{
ItemId = options . ItemId ,
MediaType = DlnaProfileType . Audio ,
@ -313,18 +292,16 @@ namespace MediaBrowser.Model.Dlna
var directPlayInfo = GetAudioDirectPlayMethods ( item , audioStream , options ) ;
var directPlayMethods = directPlayInfo . Item1 ;
transcodeReasons . AddRange ( directPlayInfo . Item2 ) ;
var conditionProcessor = new ConditionProcessor ( ) ;
var transcodeReasons = directPlayInfo . Item2 . ToList ( ) ;
int? inputAudioChannels = audioStream = = null ? null : audioStream . Channels ;
int? inputAudioBitrate = audioStream = = null ? null : audioStream . BitDepth ;
int? inputAudioSampleRate = audioStream = = null ? null : audioStream . SampleRate ;
int? inputAudioBitDepth = audioStream = = null ? null : audioStream . BitDepth ;
int? inputAudioChannels = audioStream ? . Channels ;
int? inputAudioBitrate = audioStream ? . BitDepth ;
int? inputAudioSampleRate = audioStream ? . SampleRate ;
int? inputAudioBitDepth = audioStream . BitDepth ;
if ( directPlayMethods . Count > 0 )
if ( directPlayMethods . Count ( ) > 0 )
{
string audioCodec = audioStream = = null ? null : audioStream . Codec ;
string audioCodec = audioStream ? . Codec ;
// Make sure audio codec profiles are satisfied
var conditions = new List < ProfileCondition > ( ) ;
@ -335,7 +312,7 @@ namespace MediaBrowser.Model.Dlna
bool applyConditions = true ;
foreach ( ProfileCondition applyCondition in i . ApplyConditions )
{
if ( ! c onditionProcessor. IsAudioConditionSatisfied ( applyCondition , inputAudioChannels , inputAudioBitrate , inputAudioSampleRate , inputAudioBitDepth ) )
if ( ! C onditionProcessor. IsAudioConditionSatisfied ( applyCondition , inputAudioChannels , inputAudioBitrate , inputAudioSampleRate , inputAudioBitDepth ) )
{
LogConditionFailure ( options . Profile , "AudioCodecProfile" , applyCondition , item ) ;
applyConditions = false ;
@ -345,10 +322,7 @@ namespace MediaBrowser.Model.Dlna
if ( applyConditions )
{
foreach ( ProfileCondition c in i . Conditions )
{
conditions . Add ( c ) ;
}
conditions . AddRange ( i . Conditions ) ;
}
}
}
@ -356,7 +330,7 @@ namespace MediaBrowser.Model.Dlna
bool all = true ;
foreach ( ProfileCondition c in conditions )
{
if ( ! c onditionProcessor. IsAudioConditionSatisfied ( c , inputAudioChannels , inputAudioBitrate , inputAudioSampleRate , inputAudioBitDepth ) )
if ( ! C onditionProcessor. IsAudioConditionSatisfied ( c , inputAudioChannels , inputAudioBitrate , inputAudioSampleRate , inputAudioBitDepth ) )
{
LogConditionFailure ( options . Profile , "AudioCodecProfile" , c , item ) ;
var transcodeReason = GetTranscodeReasonForFailedCondition ( c ) ;
@ -385,13 +359,12 @@ namespace MediaBrowser.Model.Dlna
TranscodingProfile transcodingProfile = null ;
foreach ( var i in options . Profile . TranscodingProfiles )
{
if ( i . Type = = playlistItem . MediaType & & i . Context = = options . Context )
if ( i . Type = = playlistItem . MediaType
& & i . Context = = options . Context
& & _transcoderSupport . CanEncodeToAudioCodec ( i . AudioCodec ? ? i . Container ) )
{
if ( _transcoderSupport . CanEncodeToAudioCodec ( i . AudioCodec ? ? i . Container ) )
{
transcodingProfile = i ;
break ;
}
transcodingProfile = i ;
break ;
}
}
@ -421,7 +394,7 @@ namespace MediaBrowser.Model.Dlna
bool applyConditions = true ;
foreach ( var applyCondition in i . ApplyConditions )
{
if ( ! c onditionProcessor. IsAudioConditionSatisfied ( applyCondition , inputAudioChannels , inputAudioBitrate , inputAudioSampleRate , inputAudioBitDepth ) )
if ( ! C onditionProcessor. IsAudioConditionSatisfied ( applyCondition , inputAudioChannels , inputAudioBitrate , inputAudioSampleRate , inputAudioBitDepth ) )
{
LogConditionFailure ( options . Profile , "AudioCodecProfile" , applyCondition , item ) ;
applyConditions = false ;
@ -463,7 +436,7 @@ namespace MediaBrowser.Model.Dlna
return playlistItem ;
}
private long? GetBitrateForDirectPlayCheck ( MediaSourceInfo item , AudioOptions options , bool isAudio )
private static long? GetBitrateForDirectPlayCheck ( MediaSourceInfo item , AudioOptions options , bool isAudio )
{
if ( item . Protocol = = MediaProtocol . File )
{
@ -473,65 +446,56 @@ namespace MediaBrowser.Model.Dlna
return options . GetMaxBitrate ( isAudio ) ;
}
private Tuple < List < PlayMethod > , List < TranscodeReason > > GetAudioDirectPlayMethods ( MediaSourceInfo item , MediaStream audioStream , AudioOptions options )
private ( IEnumerable < PlayMethod > , IEnumerable < TranscodeReason > ) GetAudioDirectPlayMethods ( MediaSourceInfo item , MediaStream audioStream , AudioOptions options )
{
var transcodeReasons = new List < TranscodeReason > ( ) ;
DirectPlayProfile directPlayProfile = options . Profile . DirectPlayProfiles
. FirstOrDefault ( x = > x . Type = = DlnaProfileType . Audio & & IsAudioDirectPlaySupported ( x , item , audioStream ) ) ;
DirectPlayProfile directPlayProfile = null ;
foreach ( var i in options . Profile . DirectPlayProfiles )
if ( directPlayProfile = = null )
{
if ( i . Type = = DlnaProfileType . Audio & & IsAudioDirectPlaySupported ( i , item , audioStream ) )
{
directPlayProfile = i ;
break ;
}
_logger . LogInformation ( "Profile: {0}, No direct play profiles found for Path: {1}" ,
options . Profile . Name ? ? "Unknown Profile" ,
item. Path ? ? "Unknown path" ) ;
return ( Enumerable . Empty < PlayMethod > ( ) , GetTranscodeReasonsFromDirectPlayProfile ( item , null , audioStream , options . Profile . DirectPlayProfiles ) ) ;
}
var playMethods = new List < PlayMethod > ( ) ;
var transcodeReasons = new List < TranscodeReason > ( ) ;
if ( directPlayProfile ! = null )
// While options takes the network and other factors into account. Only applies to direct stream
if ( item . SupportsDirectStream )
{
// While options takes the network and other factors into account. Only applies to direct stream
if ( item . SupportsDirectStream )
if ( IsAudioEligibleForDirectPlay ( item , options . GetMaxBitrate ( true ) ? ? 0 , PlayMethod . DirectStream ) )
{
if ( IsAudioEligibleForDirectPlay ( item , options . GetMaxBitrate ( true ) ? ? 0 , PlayMethod . DirectStream ) )
{
if ( options . EnableDirectStream )
{
playMethods . Add ( PlayMethod . DirectStream ) ;
}
}
else
if ( options . EnableDirectStream )
{
transcodeReasons. Add ( TranscodeReason . ContainerBitrateExceedsLimit ) ;
playMethods . Add ( PlayMethod . DirectStream ) ;
}
}
else
{
transcodeReasons . Add ( TranscodeReason . ContainerBitrateExceedsLimit ) ;
}
}
// The profile describes what the device supports
// If device requirements are satisfied then allow both direct stream and direct play
if ( item . SupportsDirectPlay )
// The profile describes what the device supports
// If device requirements are satisfied then allow both direct stream and direct play
if ( item . SupportsDirectPlay )
{
if ( IsAudioEligibleForDirectPlay ( item , GetBitrateForDirectPlayCheck ( item , options , true ) ? ? 0 , PlayMethod . DirectPlay ) )
{
if ( IsAudioEligibleForDirectPlay ( item , GetBitrateForDirectPlayCheck ( item , options , true ) ? ? 0 , PlayMethod . DirectPlay ) )
{
if ( options . EnableDirectPlay )
{
playMethods . Add ( PlayMethod . DirectPlay ) ;
}
}
else
if ( options . EnableDirectPlay )
{
transcodeReasons. Add ( TranscodeReason . ContainerBitrateExceedsLimit ) ;
playMethods . Add ( PlayMethod . DirectPlay ) ;
}
}
else
{
transcodeReasons . Add ( TranscodeReason . ContainerBitrateExceedsLimit ) ;
}
}
else
{
transcodeReasons . InsertRange ( 0 , GetTranscodeReasonsFromDirectPlayProfile ( item , null , audioStream , options . Profile . DirectPlayProfiles ) ) ;
_logger . LogInformation ( "Profile: {0}, No direct play profiles found for Path: {1}" ,
options . Profile . Name ? ? "Unknown Profile" ,
item . Path ? ? "Unknown path" ) ;
}
if ( playMethods . Count > 0 )
{
@ -542,41 +506,25 @@ namespace MediaBrowser.Model.Dlna
transcodeReasons = transcodeReasons . Distinct ( ) . ToList ( ) ;
}
return new Tuple < List < PlayMethod > , List < TranscodeReason > > ( playMethods , transcodeReasons ) ;
return ( playMethods , transcodeReasons ) ;
}
private List < TranscodeReason > GetTranscodeReasonsFromDirectPlayProfile ( MediaSourceInfo item , MediaStream videoStream , MediaStream audioStream , IEnumerable < DirectPlayProfile > directPlayProfiles )
private static List < TranscodeReason > GetTranscodeReasonsFromDirectPlayProfile ( MediaSourceInfo item , MediaStream videoStream , MediaStream audioStream , IEnumerable < DirectPlayProfile > directPlayProfiles )
{
var list = new List < TranscodeReason > ( ) ;
var containerSupported = false ;
var audioSupported = false ;
var videoSupported = false ;
foreach ( var profile in directPlayProfiles )
{
audioSupported = false ;
videoSupported = false ;
// Check container type
if ( profile . SupportsContainer ( item . Container ) )
{
containerSupported = true ;
if ( videoStream ! = null )
{
if ( profile . SupportsVideoCodec ( videoStream . Codec ) )
{
videoSupported = true ;
}
}
videoSupported = videoStream ! = null & & profile . SupportsVideoCodec ( videoStream . Codec ) ;
if ( audioStream ! = null )
{
if ( profile . SupportsAudioCodec ( audioStream . Codec ) )
{
audioSupported = true ;
}
}
audioSupported = audioStream ! = null & & profile . SupportsAudioCodec ( audioStream . Codec ) ;
if ( videoSupported & & audioSupported )
{
@ -585,6 +533,7 @@ namespace MediaBrowser.Model.Dlna
}
}
var list = new List < TranscodeReason > ( ) ;
if ( ! containerSupported )
{
list . Add ( TranscodeReason . ContainerNotSupported ) ;
@ -603,18 +552,17 @@ namespace MediaBrowser.Model.Dlna
return list ;
}
private int? GetDefaultSubtitleStreamIndex ( MediaSourceInfo item , SubtitleProfile [ ] subtitleProfiles )
private static int? GetDefaultSubtitleStreamIndex ( MediaSourceInfo item , SubtitleProfile [ ] subtitleProfiles )
{
int highestScore = - 1 ;
foreach ( var stream in item . MediaStreams )
{
if ( stream . Type = = MediaStreamType . Subtitle & & stream . Score . HasValue )
if ( stream . Type = = MediaStreamType . Subtitle
& & stream . Score . HasValue
& & stream . Score . Value > highestScore )
{
if ( stream . Score . Value > highestScore )
{
highestScore = stream . Score . Value ;
}
highestScore = stream . Score . Value ;
}
}
@ -646,7 +594,7 @@ namespace MediaBrowser.Model.Dlna
return item . DefaultSubtitleStreamIndex ;
}
private void SetStreamInfoOptionsFromTranscodingProfile ( StreamInfo playlistItem , TranscodingProfile transcodingProfile )
private static void SetStreamInfoOptionsFromTranscodingProfile ( StreamInfo playlistItem , TranscodingProfile transcodingProfile )
{
if ( string . IsNullOrEmpty ( transcodingProfile . AudioCodec ) )
{
@ -686,12 +634,10 @@ namespace MediaBrowser.Model.Dlna
}
playlistItem . SubProtocol = transcodingProfile . Protocol ;
if ( ! string . IsNullOrEmpty ( transcodingProfile . MaxAudioChannels ) )
if ( ! string . IsNullOrEmpty ( transcodingProfile . MaxAudioChannels )
& & int . TryParse ( transcodingProfile . MaxAudioChannels , NumberStyles . Any , CultureInfo . InvariantCulture , out int transcodingMaxAudioChannels ) )
{
if ( int . TryParse ( transcodingProfile . MaxAudioChannels , NumberStyles . Any , CultureInfo . InvariantCulture , out var transcodingMaxAudioChannels ) )
{
playlistItem . TranscodingMaxAudioChannels = transcodingMaxAudioChannels ;
}
playlistItem . TranscodingMaxAudioChannels = transcodingMaxAudioChannels ;
}
}
@ -702,9 +648,7 @@ namespace MediaBrowser.Model.Dlna
throw new ArgumentNullException ( nameof ( item ) ) ;
}
var transcodeReasons = new List < TranscodeReason > ( ) ;
var playlistItem = new StreamInfo
StreamInfo playlistItem = new StreamInfo
{
ItemId = options . ItemId ,
MediaType = DlnaProfileType . Video ,
@ -737,6 +681,8 @@ namespace MediaBrowser.Model.Dlna
isEligibleForDirectPlay ,
isEligibleForDirectStream ) ;
var transcodeReasons = new List < TranscodeReason > ( ) ;
if ( isEligibleForDirectPlay | | isEligibleForDirectStream )
{
// See if it can be direct played
@ -803,8 +749,6 @@ namespace MediaBrowser.Model.Dlna
SetStreamInfoOptionsFromTranscodingProfile ( playlistItem , transcodingProfile ) ;
var conditionProcessor = new ConditionProcessor ( ) ;
var isFirstAppliedCodecProfile = true ;
foreach ( var i in options . Profile . CodecProfiles )
{
@ -813,26 +757,26 @@ namespace MediaBrowser.Model.Dlna
bool applyConditions = true ;
foreach ( ProfileCondition applyCondition in i . ApplyConditions )
{
int? width = videoStream = = null ? null : videoStream . Width ;
int? height = videoStream = = null ? null : videoStream . Height ;
int? bitDepth = videoStream = = null ? null : videoStream . BitDepth ;
int? videoBitrate = videoStream = = null ? null : videoStream . BitRate ;
double? videoLevel = videoStream = = null ? null : videoStream . Level ;
string videoProfile = videoStream = = null ? null : videoStream . Profile ;
int? width = videoStream ? . Width ;
int? height = videoStream ? . Height ;
int? bitDepth = videoStream ? . BitDepth ;
int? videoBitrate = videoStream ? . BitRate ;
double? videoLevel = videoStream ? . Level ;
string videoProfile = videoStream ? . Profile ;
float videoFramerate = videoStream = = null ? 0 : videoStream . AverageFrameRate ? ? videoStream . AverageFrameRate ? ? 0 ;
bool? isAnamorphic = videoStream = = null ? null : videoStream . IsAnamorphic ;
bool? isInterlaced = videoStream = = null ? ( bool? ) null : videoStream . IsInterlaced ;
string videoCodecTag = videoStream = = null ? null : videoStream . CodecTag ;
bool? isAvc = videoStream = = null ? null : videoStream . IsAVC ;
bool? isAnamorphic = videoStream ? . IsAnamorphic ;
bool? isInterlaced = videoStream ? . IsInterlaced ;
string videoCodecTag = videoStream ? . CodecTag ;
bool? isAvc = videoStream ? . IsAVC ;
TransportStreamTimestamp ? timestamp = videoStream = = null ? TransportStreamTimestamp . None : item . Timestamp ;
int? packetLength = videoStream = = null ? null : videoStream . PacketLength ;
int? refFrames = videoStream = = null ? null : videoStream . RefFrames ;
int? packetLength = videoStream ? . PacketLength ;
int? refFrames = videoStream ? . RefFrames ;
int? numAudioStreams = item . GetStreamCount ( MediaStreamType . Audio ) ;
int? numVideoStreams = item . GetStreamCount ( MediaStreamType . Video ) ;
if ( ! c onditionProcessor. IsVideoConditionSatisfied ( applyCondition , width , height , bitDepth , videoBitrate , videoProfile , videoLevel , videoFramerate , packetLength , timestamp , isAnamorphic , isInterlaced , refFrames , numVideoStreams , numAudioStreams , videoCodecTag , isAvc ) )
if ( ! C onditionProcessor. IsVideoConditionSatisfied ( applyCondition , width , height , bitDepth , videoBitrate , videoProfile , videoLevel , videoFramerate , packetLength , timestamp , isAnamorphic , isInterlaced , refFrames , numVideoStreams , numAudioStreams , videoCodecTag , isAvc ) )
{
//LogConditionFailure(options.Profile, "VideoCodecProfile.ApplyConditions", applyCondition, item);
applyConditions = false ;
@ -876,7 +820,7 @@ namespace MediaBrowser.Model.Dlna
int? inputAudioSampleRate = audioStream = = null ? null : audioStream . SampleRate ;
int? inputAudioBitDepth = audioStream = = null ? null : audioStream . BitDepth ;
if ( ! c onditionProcessor. IsVideoAudioConditionSatisfied ( applyCondition , audioChannels , inputAudioBitrate , inputAudioSampleRate , inputAudioBitDepth , audioProfile , isSecondaryAudio ) )
if ( ! C onditionProcessor. IsVideoAudioConditionSatisfied ( applyCondition , audioChannels , inputAudioBitrate , inputAudioSampleRate , inputAudioBitDepth , audioProfile , isSecondaryAudio ) )
{
//LogConditionFailure(options.Profile, "VideoCodecProfile.ApplyConditions", applyCondition, item);
applyConditions = false ;
@ -922,7 +866,7 @@ namespace MediaBrowser.Model.Dlna
return playlistItem ;
}
private int GetDefaultAudioBitrateIfUnknown ( MediaStream audioStream )
private static int GetDefaultAudioBitrateIfUnknown ( MediaStream audioStream )
{
if ( ( audioStream . Channels ? ? 0 ) > = 6 )
{
@ -932,33 +876,37 @@ namespace MediaBrowser.Model.Dlna
return 192000 ;
}
private int GetAudioBitrate ( string subProtocol , long maxTotalBitrate , string [ ] targetAudioCodecs , MediaStream audioStream , StreamInfo item )
private static int GetAudioBitrate ( string subProtocol , long maxTotalBitrate , string [ ] targetAudioCodecs , MediaStream audioStream , StreamInfo item )
{
var targetAudioCodec = targetAudioCodecs . Length = = 0 ? null : targetAudioCodecs [ 0 ] ;
string targetAudioCodec = targetAudioCodecs . Length = = 0 ? null : targetAudioCodecs [ 0 ] ;
var targetAudioChannels = item . GetTargetAudioChannels ( targetAudioCodec ) ;
int? targetAudioChannels = item . GetTargetAudioChannels ( targetAudioCodec ) ;
int defaultBitrate = audioStream = = null ? 192000 : audioStream . BitRate ? ? GetDefaultAudioBitrateIfUnknown ( audioStream ) ;
int defaultBitrate ;
int encoderAudioBitrateLimit = int . MaxValue ;
// Reduce the bitrate if we're downmixing
if ( targetAudioChannels . HasValue & & audioStream ! = null & & audioStream . Channels . HasValue & & targetAudioChannels . Value < audioStream . Channels . Value )
if ( audioStream = = null )
{
defaultBitrate = targetAudioChannels . Value < = 2 ? 128000 : 192000 ;
defaultBitrate = 192000 ;
}
int encoderAudioBitrateLimit = int . MaxValue ;
if ( audioStream ! = null )
else
{
if ( targetAudioChannels . HasValue & & audioStream . Channels . HasValue & & targetAudioChannels . Value < audioStream . Channels . Value )
{
// Reduce the bitrate if we're downmixing
defaultBitrate = targetAudioChannels . Value < 2 ? 128000 : 192000 ;
}
else
{
defaultBitrate = audioStream . BitRate ? ? GetDefaultAudioBitrateIfUnknown ( audioStream ) ;
}
// Seeing webm encoding failures when source has 1 audio channel and 22k bitrate.
// Any attempts to transcode over 64k will fail
if ( audioStream . Channels . HasValue & &
audioStream . Channels . Value = = 1 )
if ( audioStream . Channels = = 1
& & ( audioStream . BitRate ? ? 0 ) < 64000 )
{
if ( ( audioStream . BitRate ? ? 0 ) < 64000 )
{
encoderAudioBitrateLimit = 64000 ;
}
encoderAudioBitrateLimit = 64000 ;
}
}
@ -970,19 +918,17 @@ namespace MediaBrowser.Model.Dlna
return Math . Min ( defaultBitrate , encoderAudioBitrateLimit ) ;
}
private int GetMaxAudioBitrateForTotalBitrate ( long totalBitrate )
private static int GetMaxAudioBitrateForTotalBitrate ( long totalBitrate )
{
if ( totalBitrate < = 640000 )
{
return 128000 ;
}
if ( totalBitrate < = 2000000 )
else if ( totalBitrate < = 2000000 )
{
return 384000 ;
}
if ( totalBitrate < = 3000000 )
else if ( totalBitrate < = 3000000 )
{
return 448000 ;
}
@ -990,24 +936,25 @@ namespace MediaBrowser.Model.Dlna
return 640000 ;
}
private Tuple < PlayMethod ? , List < TranscodeReason > > GetVideoDirectPlayProfile ( VideoOptions options ,
private ( PlayMethod ? , List < TranscodeReason > ) GetVideoDirectPlayProfile (
VideoOptions options ,
MediaSourceInfo mediaSource ,
MediaStream videoStream ,
MediaStream audioStream ,
bool isEligibleForDirectPlay ,
bool isEligibleForDirectStream )
{
DeviceProfile profile = options . Profile ;
if ( options . ForceDirectPlay )
{
return new Tuple < PlayMethod ? , List < TranscodeReason > > ( PlayMethod . DirectPlay , new List < TranscodeReason > ( ) ) ;
return ( PlayMethod . DirectPlay , new List < TranscodeReason > ( ) ) ;
}
if ( options . ForceDirectStream )
{
return new Tuple < PlayMethod ? , List < TranscodeReason > > ( PlayMethod . DirectStream , new List < TranscodeReason > ( ) ) ;
return ( PlayMethod . DirectStream , new List < TranscodeReason > ( ) ) ;
}
DeviceProfile profile = options . Profile ;
// See if it can be direct played
DirectPlayProfile directPlay = null ;
foreach ( var i in profile . DirectPlayProfiles )
@ -1025,7 +972,7 @@ namespace MediaBrowser.Model.Dlna
profile . Name ? ? "Unknown Profile" ,
mediaSource . Path ? ? "Unknown path" ) ;
return new Tuple < PlayMethod ? , List < TranscodeReason > > ( null , GetTranscodeReasonsFromDirectPlayProfile ( mediaSource , videoStream , audioStream , profile . DirectPlayProfiles ) ) ;
return ( null , GetTranscodeReasonsFromDirectPlayProfile ( mediaSource , videoStream , audioStream , profile . DirectPlayProfiles ) ) ;
}
string container = mediaSource . Container ;
@ -1033,8 +980,8 @@ namespace MediaBrowser.Model.Dlna
var conditions = new List < ProfileCondition > ( ) ;
foreach ( var i in profile . ContainerProfiles )
{
if ( i . Type = = DlnaProfileType . Video & &
i . ContainsContainer ( container ) )
if ( i . Type = = DlnaProfileType . Video
& & i . ContainsContainer ( container ) )
{
foreach ( var c in i . Conditions )
{
@ -1043,29 +990,27 @@ namespace MediaBrowser.Model.Dlna
}
}
var conditionProcessor = new ConditionProcessor ( ) ;
int? width = videoStream = = null ? null : videoStream . Width ;
int? height = videoStream = = null ? null : videoStream . Height ;
int? bitDepth = videoStream = = null ? null : videoStream . BitDepth ;
int? videoBitrate = videoStream = = null ? null : videoStream . BitRate ;
double? videoLevel = videoStream = = null ? null : videoStream . Level ;
string videoProfile = videoStream = = null ? null : videoStream . Profile ;
int? width = videoStream ? . Width ;
int? height = videoStream ? . Height ;
int? bitDepth = videoStream ? . BitDepth ;
int? videoBitrate = videoStream ? . BitRate ;
double? videoLevel = videoStream ? . Level ;
string videoProfile = videoStream ? . Profile ;
float videoFramerate = videoStream = = null ? 0 : videoStream . AverageFrameRate ? ? videoStream . AverageFrameRate ? ? 0 ;
bool? isAnamorphic = videoStream = = null ? null : videoStream . IsAnamorphic ;
bool? isInterlaced = videoStream = = null ? ( bool? ) null : videoStream . IsInterlaced ;
string videoCodecTag = videoStream = = null ? null : videoStream . CodecTag ;
bool? isAvc = videoStream = = null ? null : videoStream . IsAVC ;
bool? isAnamorphic = videoStream ? . IsAnamorphic ;
bool? isInterlaced = videoStream ? . IsInterlaced ;
string videoCodecTag = videoStream ? . CodecTag ;
bool? isAvc = videoStream ? . IsAVC ;
int? audioBitrate = audioStream = = null ? null : audioStream . BitRate ;
int? audioChannels = audioStream = = null ? null : audioStream . Channels ;
string audioProfile = audioStream = = null ? null : audioStream . Profile ;
int? audioSampleRate = audioStream = = null ? null : audioStream . SampleRate ;
int? audioBitDepth = audioStream = = null ? null : audioStream . BitDepth ;
int? audioBitrate = audioStream ? . BitRate ;
int? audioChannels = audioStream ? . Channels ;
string audioProfile = audioStream ? . Profile ;
int? audioSampleRate = audioStream ? . SampleRate ;
int? audioBitDepth = audioStream ? . BitDepth ;
TransportStreamTimestamp ? timestamp = videoStream = = null ? TransportStreamTimestamp . None : mediaSource . Timestamp ;
int? packetLength = videoStream = = null ? null : videoStream . PacketLength ;
int? refFrames = videoStream = = null ? null : videoStream . RefFrames ;
int? packetLength = videoStream ? . PacketLength ;
int? refFrames = videoStream ? . RefFrames ;
int? numAudioStreams = mediaSource . GetStreamCount ( MediaStreamType . Audio ) ;
int? numVideoStreams = mediaSource . GetStreamCount ( MediaStreamType . Video ) ;
@ -1073,20 +1018,20 @@ namespace MediaBrowser.Model.Dlna
// Check container conditions
foreach ( ProfileCondition i in conditions )
{
if ( ! c onditionProcessor. IsVideoConditionSatisfied ( i , width , height , bitDepth , videoBitrate , videoProfile , videoLevel , videoFramerate , packetLength , timestamp , isAnamorphic , isInterlaced , refFrames , numVideoStreams , numAudioStreams , videoCodecTag , isAvc ) )
if ( ! C onditionProcessor. IsVideoConditionSatisfied ( i , width , height , bitDepth , videoBitrate , videoProfile , videoLevel , videoFramerate , packetLength , timestamp , isAnamorphic , isInterlaced , refFrames , numVideoStreams , numAudioStreams , videoCodecTag , isAvc ) )
{
LogConditionFailure ( profile , "VideoContainerProfile" , i , mediaSource ) ;
var transcodeReason = GetTranscodeReasonForFailedCondition ( i ) ;
var transcodeReasons = transcodeReason . HasValue
? new List < TranscodeReason > { transcodeReason . Value }
: new List < TranscodeReason > { } ;
: new List < TranscodeReason > ( ) ;
return new Tuple < PlayMethod ? , List < TranscodeReason > > ( null , transcodeReasons ) ;
return ( null , transcodeReasons ) ;
}
}
string videoCodec = videoStream = = null ? null : videoStream . Codec ;
string videoCodec = videoStream ? . Codec ;
conditions = new List < ProfileCondition > ( ) ;
foreach ( var i in profile . CodecProfiles )
@ -1096,7 +1041,7 @@ namespace MediaBrowser.Model.Dlna
bool applyConditions = true ;
foreach ( ProfileCondition applyCondition in i . ApplyConditions )
{
if ( ! c onditionProcessor. IsVideoConditionSatisfied ( applyCondition , width , height , bitDepth , videoBitrate , videoProfile , videoLevel , videoFramerate , packetLength , timestamp , isAnamorphic , isInterlaced , refFrames , numVideoStreams , numAudioStreams , videoCodecTag , isAvc ) )
if ( ! C onditionProcessor. IsVideoConditionSatisfied ( applyCondition , width , height , bitDepth , videoBitrate , videoProfile , videoLevel , videoFramerate , packetLength , timestamp , isAnamorphic , isInterlaced , refFrames , numVideoStreams , numAudioStreams , videoCodecTag , isAvc ) )
{
//LogConditionFailure(profile, "VideoCodecProfile.ApplyConditions", applyCondition, mediaSource);
applyConditions = false ;
@ -1116,23 +1061,22 @@ namespace MediaBrowser.Model.Dlna
foreach ( ProfileCondition i in conditions )
{
if ( ! c onditionProcessor. IsVideoConditionSatisfied ( i , width , height , bitDepth , videoBitrate , videoProfile , videoLevel , videoFramerate , packetLength , timestamp , isAnamorphic , isInterlaced , refFrames , numVideoStreams , numAudioStreams , videoCodecTag , isAvc ) )
if ( ! C onditionProcessor. IsVideoConditionSatisfied ( i , width , height , bitDepth , videoBitrate , videoProfile , videoLevel , videoFramerate , packetLength , timestamp , isAnamorphic , isInterlaced , refFrames , numVideoStreams , numAudioStreams , videoCodecTag , isAvc ) )
{
LogConditionFailure ( profile , "VideoCodecProfile" , i , mediaSource ) ;
var transcodeReason = GetTranscodeReasonForFailedCondition ( i ) ;
var transcodeReasons = transcodeReason . HasValue
? new List < TranscodeReason > { transcodeReason . Value }
: new List < TranscodeReason > { } ;
: new List < TranscodeReason > ( ) ;
return new Tuple < PlayMethod ? , List < TranscodeReason > > ( null , transcodeReasons ) ;
return ( null , transcodeReasons ) ;
}
}
if ( audioStream ! = null )
{
string audioCodec = audioStream . Codec ;
conditions = new List < ProfileCondition > ( ) ;
bool? isSecondaryAudio = audioStream = = null ? null : mediaSource . IsSecondaryAudio ( audioStream ) ;
@ -1143,7 +1087,7 @@ namespace MediaBrowser.Model.Dlna
bool applyConditions = true ;
foreach ( ProfileCondition applyCondition in i . ApplyConditions )
{
if ( ! c onditionProcessor. IsVideoAudioConditionSatisfied ( applyCondition , audioChannels , audioBitrate , audioSampleRate , audioBitDepth , audioProfile , isSecondaryAudio ) )
if ( ! C onditionProcessor. IsVideoAudioConditionSatisfied ( applyCondition , audioChannels , audioBitrate , audioSampleRate , audioBitDepth , audioProfile , isSecondaryAudio ) )
{
//LogConditionFailure(profile, "VideoAudioCodecProfile.ApplyConditions", applyCondition, mediaSource);
applyConditions = false ;
@ -1163,26 +1107,26 @@ namespace MediaBrowser.Model.Dlna
foreach ( ProfileCondition i in conditions )
{
if ( ! c onditionProcessor. IsVideoAudioConditionSatisfied ( i , audioChannels , audioBitrate , audioSampleRate , audioBitDepth , audioProfile , isSecondaryAudio ) )
if ( ! C onditionProcessor. IsVideoAudioConditionSatisfied ( i , audioChannels , audioBitrate , audioSampleRate , audioBitDepth , audioProfile , isSecondaryAudio ) )
{
LogConditionFailure ( profile , "VideoAudioCodecProfile" , i , mediaSource ) ;
var transcodeReason = GetTranscodeReasonForFailedCondition ( i ) ;
var transcodeReasons = transcodeReason . HasValue
? new List < TranscodeReason > { transcodeReason . Value }
: new List < TranscodeReason > { } ;
: new List < TranscodeReason > ( ) ;
return new Tuple < PlayMethod ? , List < TranscodeReason > > ( null , transcodeReasons ) ;
return ( null , transcodeReasons ) ;
}
}
}
if ( isEligibleForDirectStream & & mediaSource . SupportsDirectStream )
{
return new Tuple < PlayMethod ? , List < TranscodeReason > > ( PlayMethod . DirectStream , new List < TranscodeReason > ( ) ) ;
return ( PlayMethod . DirectStream , new List < TranscodeReason > ( ) ) ;
}
return new Tuple < PlayMethod ? , List < TranscodeReason > > ( null , new List < TranscodeReason > { TranscodeReason . ContainerBitrateExceedsLimit } ) ;
return ( null , new List < TranscodeReason > { TranscodeReason . ContainerBitrateExceedsLimit } ) ;
}
private void LogConditionFailure ( DeviceProfile profile , string type , ProfileCondition condition , MediaSourceInfo mediaSource )
@ -1197,7 +1141,8 @@ namespace MediaBrowser.Model.Dlna
mediaSource . Path ? ? "Unknown path" ) ;
}
private ValueTuple < bool , TranscodeReason ? > IsEligibleForDirectPlay ( MediaSourceInfo item ,
private ( bool directPlay , TranscodeReason ? reason ) IsEligibleForDirectPlay (
MediaSourceInfo item ,
long maxBitrate ,
MediaStream subtitleStream ,
VideoOptions options ,
@ -1210,21 +1155,23 @@ namespace MediaBrowser.Model.Dlna
if ( subtitleProfile . Method ! = SubtitleDeliveryMethod . External & & subtitleProfile . Method ! = SubtitleDeliveryMethod . Embed )
{
_logger . LogInformation ( "Not eligible for {0} due to unsupported subtitles" , playMethod ) ;
return new ValueTuple < bool , TranscodeReason ? > ( false , TranscodeReason . SubtitleCodecNotSupported ) ;
return ( false , TranscodeReason . SubtitleCodecNotSupported ) ;
}
}
var result = IsAudioEligibleForDirectPlay ( item , maxBitrate , playMethod ) ;
if ( result )
{
return new ValueTuple < bool , TranscodeReason ? > ( result , null ) ;
}
bool result = IsAudioEligibleForDirectPlay ( item , maxBitrate , playMethod ) ;
return new ValueTuple < bool , TranscodeReason ? > ( result , TranscodeReason . ContainerBitrateExceedsLimit ) ;
return ( result , result ? ( TranscodeReason ? ) null : TranscodeReason . ContainerBitrateExceedsLimit ) ;
}
public static SubtitleProfile GetSubtitleProfile ( MediaSourceInfo mediaSource , MediaStream subtitleStream , SubtitleProfile [ ] subtitleProfiles , PlayMethod playMethod , ITranscoderSupport transcoderSupport , string outputContainer , string transcodingSubProtocol )
public static SubtitleProfile GetSubtitleProfile (
MediaSourceInfo mediaSource ,
MediaStream subtitleStream ,
SubtitleProfile [ ] subtitleProfiles ,
PlayMethod playMethod ,
ITranscoderSupport transcoderSupport ,
string outputContainer ,
string transcodingSubProtocol )
{
if ( ! subtitleStream . IsExternal & & ( playMethod ! = PlayMethod . Transcode | | ! string . Equals ( transcodingSubProtocol , "hls" , StringComparison . OrdinalIgnoreCase ) ) )
{
@ -1301,27 +1248,20 @@ namespace MediaBrowser.Model.Dlna
{
if ( ! string . IsNullOrEmpty ( transcodingContainer ) )
{
var normalizedContainers = ContainerProfile . SplitValue ( transcodingContainer ) ;
string[ ] normalizedContainers = ContainerProfile . SplitValue ( transcodingContainer ) ;
if ( ContainerProfile . ContainsContainer ( normalizedContainers , "ts" ) )
{
return false ;
}
if ( ContainerProfile . ContainsContainer ( normalizedContainers , "mpegts" ) )
{
return false ;
}
if ( ContainerProfile . ContainsContainer ( normalizedContainers , "mp4" ) )
if ( ContainerProfile . ContainsContainer ( normalizedContainers , "ts" )
| | ContainerProfile . ContainsContainer ( normalizedContainers , "mpegts" )
| | ContainerProfile . ContainsContainer ( normalizedContainers , "mp4" ) )
{
return false ;
}
if ( ContainerProfile . ContainsContainer ( normalizedContainers , "mkv" ) | |
ContainerProfile . ContainsContainer ( normalizedContainers , "matroska" ) )
else if ( ContainerProfile . ContainsContainer ( normalizedContainers , "mkv" )
| | ContainerProfile . ContainsContainer ( normalizedContainers , "matroska" ) )
{
return true ;
}
}
return false ;
}
@ -1388,22 +1328,22 @@ namespace MediaBrowser.Model.Dlna
return true ;
}
var requestedMaxBitrate = maxBitrate > 0 ? maxBitrate : 1000000 ;
long requestedMaxBitrate = maxBitrate > 0 ? maxBitrate : 1000000 ;
// If we don't know the bitrate, then force a transcode if requested max bitrate is under 40 mbps
var itemBitrate = item . Bitrate ? ?
40000000 ;
int itemBitrate = item . Bitrate ? ? 40000000 ;
if ( itemBitrate > requestedMaxBitrate )
{
_logger . LogInformation ( "Bitrate exceeds " + playMethod + " limit: media bitrate: {0}, max bitrate: {1}" , itemBitrate . ToString ( CultureInfo . InvariantCulture ) , requestedMaxBitrate . ToString ( CultureInfo . InvariantCulture ) ) ;
_logger . LogInformation ( "Bitrate exceeds {PlayBackMethod} limit: media bitrate: {MediaBitrate}, max bitrate: {MaxBitrate}" ,
playMethod , itemBitrate , requestedMaxBitrate ) ;
return false ;
}
return true ;
}
private void ValidateInput ( VideoOptions options )
private static void ValidateInput ( VideoOptions options )
{
ValidateAudioInput ( options ) ;
@ -1418,7 +1358,7 @@ namespace MediaBrowser.Model.Dlna
}
}
private void ValidateAudioInput ( AudioOptions options )
private static void ValidateAudioInput ( AudioOptions options )
{
if ( options . ItemId . Equals ( Guid . Empty ) )
{
@ -1438,32 +1378,6 @@ namespace MediaBrowser.Model.Dlna
}
}
private void ApplyTranscodingConditions ( StreamInfo item , List < CodecProfile > codecProfiles )
{
foreach ( var profile in codecProfiles )
{
ApplyTranscodingConditions ( item , profile ) ;
}
}
private void ApplyTranscodingConditions ( StreamInfo item , CodecProfile codecProfile )
{
var codecs = ContainerProfile . SplitValue ( codecProfile . Codec ) ;
if ( codecs . Length = = 0 )
{
ApplyTranscodingConditions ( item , codecProfile . Conditions , null , true , true ) ;
return ;
}
var enableNonQualified = true ;
foreach ( var codec in codecs )
{
ApplyTranscodingConditions ( item , codecProfile . Conditions , codec , true , enableNonQualified ) ;
enableNonQualified = false ;
}
}
private void ApplyTranscodingConditions ( StreamInfo item , IEnumerable < ProfileCondition > conditions , string qualifier , bool enableQualifiedConditions , bool enableNonQualifiedConditions )
{
foreach ( ProfileCondition condition in conditions )
@ -1838,7 +1752,7 @@ namespace MediaBrowser.Model.Dlna
}
}
private bool IsAudioDirectPlaySupported ( DirectPlayProfile profile , MediaSourceInfo item , MediaStream audioStream )
private static bool IsAudioDirectPlaySupported ( DirectPlayProfile profile , MediaSourceInfo item , MediaStream audioStream )
{
// Check container type
if ( ! profile . SupportsContainer ( item . Container ) )
@ -1847,7 +1761,7 @@ namespace MediaBrowser.Model.Dlna
}
// Check audio codec
string audioCodec = audioStream = = null ? null : audioStream . Codec ;
string audioCodec = audioStream ? . Codec ;
if ( ! profile . SupportsAudioCodec ( audioCodec ) )
{
return false ;
@ -1865,20 +1779,16 @@ namespace MediaBrowser.Model.Dlna
}
// Check video codec
string videoCodec = videoStream = = null ? null : videoStream . Codec ;
string videoCodec = videoStream ? . Codec ;
if ( ! profile . SupportsVideoCodec ( videoCodec ) )
{
return false ;
}
// Check audio codec
if ( audioStream ! = null )
if ( audioStream ! = null & & ! profile . SupportsAudioCodec ( audioStream . Codec ) )
{
string audioCodec = audioStream = = null ? null : audioStream . Codec ;
if ( ! profile . SupportsAudioCodec ( audioCodec ) )
{
return false ;
}
return false ;
}
return true ;